blob: c7c6be9152651a873a5ceb697bc0571a11dbaf29 [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///
Chris Lattner5b454732009-01-05 03:55:46 +000023/// Note that this routine will not parse ::new or ::delete.
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000024///
25/// '::'[opt] nested-name-specifier
26/// '::'
27///
28/// nested-name-specifier:
29/// type-name '::'
30/// namespace-name '::'
31/// nested-name-specifier identifier '::'
32/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
33///
Chris Lattner5b454732009-01-05 03:55:46 +000034bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS) {
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000035 assert(getLang().CPlusPlus &&
Chris Lattner7452c6f2009-01-05 01:24:05 +000036 "Call sites of this function should be guarded by checking for C++");
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000037
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000038 if (Tok.is(tok::annot_cxxscope)) {
39 SS.setScopeRep(Tok.getAnnotationValue());
40 SS.setRange(Tok.getAnnotationRange());
41 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000042 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000043 }
Chris Lattnere607e802009-01-04 21:14:15 +000044
Chris Lattner5b454732009-01-05 03:55:46 +000045 if (Tok.is(tok::coloncolon)) {
46 // ::new and ::delete aren't nested-name-specifiers.
47 tok::TokenKind NextKind = NextToken().getKind();
48 if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
49 return false;
Chris Lattner55a7cef2009-01-05 00:13:00 +000050
Chris Lattner55a7cef2009-01-05 00:13:00 +000051 // '::' - Global scope qualifier.
Chris Lattner357089d2009-01-05 02:07:19 +000052 SourceLocation CCLoc = ConsumeToken();
Chris Lattner357089d2009-01-05 02:07:19 +000053 SS.setBeginLoc(CCLoc);
54 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
55 SS.setEndLoc(CCLoc);
56 } else if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
57 SS.setBeginLoc(Tok.getLocation());
58 } else {
59 // Not a CXXScopeSpecifier.
60 return false;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000061 }
62
63 // nested-name-specifier:
64 // type-name '::'
65 // namespace-name '::'
66 // nested-name-specifier identifier '::'
67 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000068 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
69 IdentifierInfo *II = Tok.getIdentifierInfo();
70 SourceLocation IdLoc = ConsumeToken();
Chris Lattnere607e802009-01-04 21:14:15 +000071 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000072 SourceLocation CCLoc = ConsumeToken();
73 if (SS.isInvalid())
74 continue;
75
76 SS.setScopeRep(
Chris Lattnere607e802009-01-04 21:14:15 +000077 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000078 SS.setEndLoc(CCLoc);
79 }
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000080
81 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000082}
83
84/// ParseCXXIdExpression - Handle id-expression.
85///
86/// id-expression:
87/// unqualified-id
88/// qualified-id
89///
90/// unqualified-id:
91/// identifier
92/// operator-function-id
93/// conversion-function-id [TODO]
94/// '~' class-name [TODO]
95/// template-id [TODO]
96///
97/// qualified-id:
98/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
99/// '::' identifier
100/// '::' operator-function-id
101/// '::' template-id [TODO]
102///
103/// nested-name-specifier:
104/// type-name '::'
105/// namespace-name '::'
106/// nested-name-specifier identifier '::'
107/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
108///
109/// NOTE: The standard specifies that, for qualified-id, the parser does not
110/// expect:
111///
112/// '::' conversion-function-id
113/// '::' '~' class-name
114///
115/// This may cause a slight inconsistency on diagnostics:
116///
117/// class C {};
118/// namespace A {}
119/// void f() {
120/// :: A :: ~ C(); // Some Sema error about using destructor with a
121/// // namespace.
122/// :: ~ C(); // Some Parser error like 'unexpected ~'.
123/// }
124///
125/// We simplify the parser a bit and make it work like:
126///
127/// qualified-id:
128/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
129/// '::' unqualified-id
130///
131/// That way Sema can handle and report similar errors for namespaces and the
132/// global scope.
133///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000134Parser::OwningExprResult Parser::ParseCXXIdExpression() {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000135 // qualified-id:
136 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
137 // '::' unqualified-id
138 //
139 CXXScopeSpec SS;
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000140 MaybeParseCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000141
142 // unqualified-id:
143 // identifier
144 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000145 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000146 // '~' class-name [TODO]
147 // template-id [TODO]
148 //
149 switch (Tok.getKind()) {
150 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000151 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000152
153 case tok::identifier: {
154 // Consume the identifier so that we can see if it is followed by a '('.
155 IdentifierInfo &II = *Tok.getIdentifierInfo();
156 SourceLocation L = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000157 return Owned(Actions.ActOnIdentifierExpr(CurScope, L, II,
158 Tok.is(tok::l_paren), &SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000159 }
160
161 case tok::kw_operator: {
162 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000163 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000164 return Owned(Actions.ActOnCXXOperatorFunctionIdExpr(
165 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS));
Chris Lattner7452c6f2009-01-05 01:24:05 +0000166 if (TypeTy *Type = ParseConversionFunctionId())
167 return Owned(Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc,
168 Type,
169 Tok.is(tok::l_paren), SS));
Sebastian Redl20df9b72008-12-11 22:51:44 +0000170
Douglas Gregor2def4832008-11-17 20:34:05 +0000171 // We already complained about a bad conversion-function-id,
172 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000173 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000174 }
175
176 } // switch.
177
178 assert(0 && "The switch was supposed to take care everything.");
179}
180
Reid Spencer5f016e22007-07-11 17:01:13 +0000181/// ParseCXXCasts - This handles the various ways to cast expressions to another
182/// type.
183///
184/// postfix-expression: [C++ 5.2p1]
185/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
186/// 'static_cast' '<' type-name '>' '(' expression ')'
187/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
188/// 'const_cast' '<' type-name '>' '(' expression ')'
189///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000190Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000191 tok::TokenKind Kind = Tok.getKind();
192 const char *CastName = 0; // For error messages
193
194 switch (Kind) {
195 default: assert(0 && "Unknown C++ cast!"); abort();
196 case tok::kw_const_cast: CastName = "const_cast"; break;
197 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
198 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
199 case tok::kw_static_cast: CastName = "static_cast"; break;
200 }
201
202 SourceLocation OpLoc = ConsumeToken();
203 SourceLocation LAngleBracketLoc = Tok.getLocation();
204
205 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000206 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000207
208 TypeTy *CastTy = ParseTypeName();
209 SourceLocation RAngleBracketLoc = Tok.getLocation();
210
Chris Lattner1ab3b962008-11-18 07:48:38 +0000211 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000212 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000213
214 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
215
Chris Lattner1ab3b962008-11-18 07:48:38 +0000216 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000217 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000218
Sebastian Redld8c4e152008-12-11 22:33:27 +0000219 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000220
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000221 if (!Result.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000222 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
223 LAngleBracketLoc, CastTy, RAngleBracketLoc,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000224 LParenLoc, Result.release(), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000225
Sebastian Redl20df9b72008-12-11 22:51:44 +0000226 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000227}
228
Sebastian Redlc42e1182008-11-11 11:37:55 +0000229/// ParseCXXTypeid - This handles the C++ typeid expression.
230///
231/// postfix-expression: [C++ 5.2p1]
232/// 'typeid' '(' expression ')'
233/// 'typeid' '(' type-id ')'
234///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000235Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000236 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
237
238 SourceLocation OpLoc = ConsumeToken();
239 SourceLocation LParenLoc = Tok.getLocation();
240 SourceLocation RParenLoc;
241
242 // typeid expressions are always parenthesized.
243 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
244 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000245 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000246
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000247 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000248
249 if (isTypeIdInParens()) {
250 TypeTy *Ty = ParseTypeName();
251
252 // Match the ')'.
253 MatchRHSPunctuation(tok::r_paren, LParenLoc);
254
255 if (!Ty)
Sebastian Redl20df9b72008-12-11 22:51:44 +0000256 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000257
258 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
259 Ty, RParenLoc);
260 } else {
261 Result = ParseExpression();
262
263 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000264 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000265 SkipUntil(tok::r_paren);
266 else {
267 MatchRHSPunctuation(tok::r_paren, LParenLoc);
268
269 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000270 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000271 }
272 }
273
Sebastian Redl20df9b72008-12-11 22:51:44 +0000274 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000275}
276
Reid Spencer5f016e22007-07-11 17:01:13 +0000277/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
278///
279/// boolean-literal: [C++ 2.13.5]
280/// 'true'
281/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000282Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000283 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000284 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
Reid Spencer5f016e22007-07-11 17:01:13 +0000285}
Chris Lattner50dd2892008-02-26 00:51:44 +0000286
287/// ParseThrowExpression - This handles the C++ throw expression.
288///
289/// throw-expression: [C++ 15]
290/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000291Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000292 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000293 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000294
Chris Lattner2a2819a2008-04-06 06:02:23 +0000295 // If the current token isn't the start of an assignment-expression,
296 // then the expression is not present. This handles things like:
297 // "C ? throw : (void)42", which is crazy but legal.
298 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
299 case tok::semi:
300 case tok::r_paren:
301 case tok::r_square:
302 case tok::r_brace:
303 case tok::colon:
304 case tok::comma:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000305 return Owned(Actions.ActOnCXXThrow(ThrowLoc));
Chris Lattner50dd2892008-02-26 00:51:44 +0000306
Chris Lattner2a2819a2008-04-06 06:02:23 +0000307 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000308 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000309 if (Expr.isInvalid()) return move(Expr);
310 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000311 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000312}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000313
314/// ParseCXXThis - This handles the C++ 'this' pointer.
315///
316/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
317/// a non-lvalue expression whose value is the address of the object for which
318/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000319Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000320 assert(Tok.is(tok::kw_this) && "Not 'this'!");
321 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000322 return Owned(Actions.ActOnCXXThis(ThisLoc));
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000323}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000324
325/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
326/// Can be interpreted either as function-style casting ("int(x)")
327/// or class type construction ("ClassType(x,y,z)")
328/// or creation of a value-initialized type ("int()").
329///
330/// postfix-expression: [C++ 5.2p1]
331/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
332/// typename-specifier '(' expression-list[opt] ')' [TODO]
333///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000334Parser::OwningExprResult
335Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000336 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
337 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
338
339 assert(Tok.is(tok::l_paren) && "Expected '('!");
340 SourceLocation LParenLoc = ConsumeParen();
341
Sebastian Redla55e52c2008-11-25 22:21:31 +0000342 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000343 CommaLocsTy CommaLocs;
344
345 if (Tok.isNot(tok::r_paren)) {
346 if (ParseExpressionList(Exprs, CommaLocs)) {
347 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000348 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000349 }
350 }
351
352 // Match the ')'.
353 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
354
355 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
356 "Unexpected number of commas!");
Sebastian Redl20df9b72008-12-11 22:51:44 +0000357 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
358 LParenLoc,
359 Exprs.take(), Exprs.size(),
360 &CommaLocs[0], RParenLoc));
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000361}
362
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000363/// ParseCXXCondition - if/switch/while/for condition expression.
364///
365/// condition:
366/// expression
367/// type-specifier-seq declarator '=' assignment-expression
368/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
369/// '=' assignment-expression
370///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000371Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000372 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000373 return ParseExpression(); // expression
374
375 SourceLocation StartLoc = Tok.getLocation();
376
377 // type-specifier-seq
378 DeclSpec DS;
379 ParseSpecifierQualifierList(DS);
380
381 // declarator
382 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
383 ParseDeclarator(DeclaratorInfo);
384
385 // simple-asm-expr[opt]
386 if (Tok.is(tok::kw_asm)) {
Sebastian Redleffa8d12008-12-10 00:02:53 +0000387 OwningExprResult AsmLabel(ParseSimpleAsm());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000388 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000389 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000390 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000391 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000392 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000393 }
394
395 // If attributes are present, parse them.
396 if (Tok.is(tok::kw___attribute))
397 DeclaratorInfo.AddAttributes(ParseAttributes());
398
399 // '=' assignment-expression
400 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000401 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000402 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000403 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000404 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000405 return ExprError();
406
407 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
408 DeclaratorInfo,EqualLoc,
409 AssignExpr.release()));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000410}
411
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000412/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
413/// This should only be called when the current token is known to be part of
414/// simple-type-specifier.
415///
416/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000417/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000418/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
419/// char
420/// wchar_t
421/// bool
422/// short
423/// int
424/// long
425/// signed
426/// unsigned
427/// float
428/// double
429/// void
430/// [GNU] typeof-specifier
431/// [C++0x] auto [TODO]
432///
433/// type-name:
434/// class-name
435/// enum-name
436/// typedef-name
437///
438void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
439 DS.SetRangeStart(Tok.getLocation());
440 const char *PrevSpec;
441 SourceLocation Loc = Tok.getLocation();
442
443 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000444 case tok::identifier: // foo::bar
445 case tok::coloncolon: // ::foo::bar
446 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000447 default:
448 assert(0 && "Not a simple-type-specifier token!");
449 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000450
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000451 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000452 case tok::annot_qualtypename: {
453 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
454 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000455 break;
456 }
457
458 // builtin types
459 case tok::kw_short:
460 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
461 break;
462 case tok::kw_long:
463 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
464 break;
465 case tok::kw_signed:
466 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
467 break;
468 case tok::kw_unsigned:
469 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
470 break;
471 case tok::kw_void:
472 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
473 break;
474 case tok::kw_char:
475 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
476 break;
477 case tok::kw_int:
478 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
479 break;
480 case tok::kw_float:
481 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
482 break;
483 case tok::kw_double:
484 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
485 break;
486 case tok::kw_wchar_t:
487 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
488 break;
489 case tok::kw_bool:
490 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
491 break;
492
493 // GNU typeof support.
494 case tok::kw_typeof:
495 ParseTypeofSpecifier(DS);
496 DS.Finish(Diags, PP.getSourceManager(), getLang());
497 return;
498 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000499 if (Tok.is(tok::annot_qualtypename))
500 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
501 else
502 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000503 ConsumeToken();
504 DS.Finish(Diags, PP.getSourceManager(), getLang());
505}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000506
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000507/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
508/// [dcl.name]), which is a non-empty sequence of type-specifiers,
509/// e.g., "const short int". Note that the DeclSpec is *not* finished
510/// by parsing the type-specifier-seq, because these sequences are
511/// typically followed by some form of declarator. Returns true and
512/// emits diagnostics if this is not a type-specifier-seq, false
513/// otherwise.
514///
515/// type-specifier-seq: [C++ 8.1]
516/// type-specifier type-specifier-seq[opt]
517///
518bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
519 DS.SetRangeStart(Tok.getLocation());
520 const char *PrevSpec = 0;
521 int isInvalid = 0;
522
523 // Parse one or more of the type specifiers.
524 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000525 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000526 return true;
527 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000528 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000529
530 return false;
531}
532
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000533/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000534/// operator name (C++ [over.oper]). If successful, returns the
535/// predefined identifier that corresponds to that overloaded
536/// operator. Otherwise, returns NULL and does not consume any tokens.
537///
538/// operator-function-id: [C++ 13.5]
539/// 'operator' operator
540///
541/// operator: one of
542/// new delete new[] delete[]
543/// + - * / % ^ & | ~
544/// ! = < > += -= *= /= %=
545/// ^= &= |= << >> >>= <<= == !=
546/// <= >= && || ++ -- , ->* ->
547/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000548OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000549 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000550
551 OverloadedOperatorKind Op = OO_None;
552 switch (NextToken().getKind()) {
553 case tok::kw_new:
554 ConsumeToken(); // 'operator'
555 ConsumeToken(); // 'new'
556 if (Tok.is(tok::l_square)) {
557 ConsumeBracket(); // '['
558 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
559 Op = OO_Array_New;
560 } else {
561 Op = OO_New;
562 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000563 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000564
565 case tok::kw_delete:
566 ConsumeToken(); // 'operator'
567 ConsumeToken(); // 'delete'
568 if (Tok.is(tok::l_square)) {
569 ConsumeBracket(); // '['
570 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
571 Op = OO_Array_Delete;
572 } else {
573 Op = OO_Delete;
574 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000575 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000576
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000577#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000578 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000579#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000580#include "clang/Basic/OperatorKinds.def"
581
582 case tok::l_paren:
583 ConsumeToken(); // 'operator'
584 ConsumeParen(); // '('
585 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000586 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000587
588 case tok::l_square:
589 ConsumeToken(); // 'operator'
590 ConsumeBracket(); // '['
591 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000592 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000593
594 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000595 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000596 }
597
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000598 ConsumeToken(); // 'operator'
599 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000600 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000601}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000602
603/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
604/// which expresses the name of a user-defined conversion operator
605/// (C++ [class.conv.fct]p1). Returns the type that this operator is
606/// specifying a conversion for, or NULL if there was an error.
607///
608/// conversion-function-id: [C++ 12.3.2]
609/// operator conversion-type-id
610///
611/// conversion-type-id:
612/// type-specifier-seq conversion-declarator[opt]
613///
614/// conversion-declarator:
615/// ptr-operator conversion-declarator[opt]
616Parser::TypeTy *Parser::ParseConversionFunctionId() {
617 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
618 ConsumeToken(); // 'operator'
619
620 // Parse the type-specifier-seq.
621 DeclSpec DS;
622 if (ParseCXXTypeSpecifierSeq(DS))
623 return 0;
624
625 // Parse the conversion-declarator, which is merely a sequence of
626 // ptr-operators.
627 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000628 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000629
630 // Finish up the type.
631 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
632 if (Result.isInvalid)
633 return 0;
634 else
635 return Result.Val;
636}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000637
638/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
639/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000640///
641/// This method is called to parse the new expression after the optional :: has
642/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
643/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000644///
645/// new-expression:
646/// '::'[opt] 'new' new-placement[opt] new-type-id
647/// new-initializer[opt]
648/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
649/// new-initializer[opt]
650///
651/// new-placement:
652/// '(' expression-list ')'
653///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000654/// new-type-id:
655/// type-specifier-seq new-declarator[opt]
656///
657/// new-declarator:
658/// ptr-operator new-declarator[opt]
659/// direct-new-declarator
660///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000661/// new-initializer:
662/// '(' expression-list[opt] ')'
663/// [C++0x] braced-init-list [TODO]
664///
Chris Lattner59232d32009-01-04 21:25:24 +0000665Parser::OwningExprResult
666Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
667 assert(Tok.is(tok::kw_new) && "expected 'new' token");
668 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000669
670 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
671 // second form of new-expression. It can't be a new-type-id.
672
Sebastian Redla55e52c2008-11-25 22:21:31 +0000673 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000674 SourceLocation PlacementLParen, PlacementRParen;
675
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000676 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000677 DeclSpec DS;
678 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000679 if (Tok.is(tok::l_paren)) {
680 // If it turns out to be a placement, we change the type location.
681 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000682 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
683 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000684 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000685 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000686
687 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000688 if (PlacementRParen.isInvalid()) {
689 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000690 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000691 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000692
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000693 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000694 // Reset the placement locations. There was no placement.
695 PlacementLParen = PlacementRParen = SourceLocation();
696 ParenTypeId = true;
697 } else {
698 // We still need the type.
699 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000700 SourceLocation LParen = ConsumeParen();
701 ParseSpecifierQualifierList(DS);
702 ParseDeclarator(DeclaratorInfo);
703 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000704 ParenTypeId = true;
705 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000706 if (ParseCXXTypeSpecifierSeq(DS))
707 DeclaratorInfo.setInvalidType(true);
708 else
709 ParseDeclaratorInternal(DeclaratorInfo,
710 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000711 ParenTypeId = false;
712 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000713 }
714 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000715 // A new-type-id is a simplified type-id, where essentially the
716 // direct-declarator is replaced by a direct-new-declarator.
717 if (ParseCXXTypeSpecifierSeq(DS))
718 DeclaratorInfo.setInvalidType(true);
719 else
720 ParseDeclaratorInternal(DeclaratorInfo,
721 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000722 ParenTypeId = false;
723 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000724 if (DeclaratorInfo.getInvalidType()) {
725 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000726 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000727 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000728
Sebastian Redla55e52c2008-11-25 22:21:31 +0000729 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000730 SourceLocation ConstructorLParen, ConstructorRParen;
731
732 if (Tok.is(tok::l_paren)) {
733 ConstructorLParen = ConsumeParen();
734 if (Tok.isNot(tok::r_paren)) {
735 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000736 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
737 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000738 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000739 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000740 }
741 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000742 if (ConstructorRParen.isInvalid()) {
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 }
747
Sebastian Redl20df9b72008-12-11 22:51:44 +0000748 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
749 PlacementArgs.take(), PlacementArgs.size(),
750 PlacementRParen, ParenTypeId, DeclaratorInfo,
751 ConstructorLParen, ConstructorArgs.take(),
752 ConstructorArgs.size(), ConstructorRParen));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000753}
754
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000755/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
756/// passed to ParseDeclaratorInternal.
757///
758/// direct-new-declarator:
759/// '[' expression ']'
760/// direct-new-declarator '[' constant-expression ']'
761///
Chris Lattner59232d32009-01-04 21:25:24 +0000762void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000763 // Parse the array dimensions.
764 bool first = true;
765 while (Tok.is(tok::l_square)) {
766 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000767 OwningExprResult Size(first ? ParseExpression()
768 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000769 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000770 // Recover
771 SkipUntil(tok::r_square);
772 return;
773 }
774 first = false;
775
776 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000777 Size.release(), LLoc));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000778
779 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
780 return;
781 }
782}
783
784/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
785/// This ambiguity appears in the syntax of the C++ new operator.
786///
787/// new-expression:
788/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
789/// new-initializer[opt]
790///
791/// new-placement:
792/// '(' expression-list ')'
793///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000794bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +0000795 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000796 // The '(' was already consumed.
797 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000798 ParseSpecifierQualifierList(D.getMutableDeclSpec());
799 ParseDeclarator(D);
800 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000801 }
802
803 // It's not a type, it has to be an expression list.
804 // Discard the comma locations - ActOnCXXNew has enough parameters.
805 CommaLocsTy CommaLocs;
806 return ParseExpressionList(PlacementArgs, CommaLocs);
807}
808
809/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
810/// to free memory allocated by new.
811///
Chris Lattner59232d32009-01-04 21:25:24 +0000812/// This method is called to parse the 'delete' expression after the optional
813/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
814/// and "Start" is its location. Otherwise, "Start" is the location of the
815/// 'delete' token.
816///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000817/// delete-expression:
818/// '::'[opt] 'delete' cast-expression
819/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +0000820Parser::OwningExprResult
821Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
822 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
823 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000824
825 // Array delete?
826 bool ArrayDelete = false;
827 if (Tok.is(tok::l_square)) {
828 ArrayDelete = true;
829 SourceLocation LHS = ConsumeBracket();
830 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
831 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000832 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000833 }
834
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000835 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000836 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000837 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000838
Sebastian Redl20df9b72008-12-11 22:51:44 +0000839 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
840 Operand.release()));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000841}