blob: fb60bde4f1ea49cd3ea3211dabec03bb17592ed9 [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
Chris Lattner500d3292009-01-29 05:15:15 +000014#include "clang/Parse/ParseDiagnostic.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000015#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
Chris Lattner7a0ab5f2009-01-06 06:59:53 +000020/// ParseOptionalCXXScopeSpecifier - Parse global scope or
21/// nested-name-specifier if present. Returns true if a nested-name-specifier
22/// was parsed from the token stream. Note that this routine will not parse
23/// ::new or ::delete, it will just leave them in the token stream.
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 Lattner7a0ab5f2009-01-06 06:59:53 +000034bool Parser::ParseOptionalCXXScopeSpecifier(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 Redlebc07d52009-02-03 20:19:35 +0000134/// The isAddressOfOperand parameter indicates that this id-expression is a
135/// direct operand of the address-of operator. This is, besides member contexts,
136/// the only place where a qualified-id naming a non-static class member may
137/// appear.
138///
139Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000140 // qualified-id:
141 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
142 // '::' unqualified-id
143 //
144 CXXScopeSpec SS;
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000145 ParseOptionalCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000146
147 // unqualified-id:
148 // identifier
149 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000150 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000151 // '~' class-name [TODO]
152 // template-id [TODO]
153 //
154 switch (Tok.getKind()) {
155 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000156 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000157
158 case tok::identifier: {
159 // Consume the identifier so that we can see if it is followed by a '('.
160 IdentifierInfo &II = *Tok.getIdentifierInfo();
161 SourceLocation L = ConsumeToken();
Sebastian Redlebc07d52009-02-03 20:19:35 +0000162 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
163 &SS, isAddressOfOperand);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000164 }
165
166 case tok::kw_operator: {
167 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000168 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000169 return Actions.ActOnCXXOperatorFunctionIdExpr(
Sebastian Redlebc07d52009-02-03 20:19:35 +0000170 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
171 isAddressOfOperand);
Chris Lattner7452c6f2009-01-05 01:24:05 +0000172 if (TypeTy *Type = ParseConversionFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000173 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
Sebastian Redlebc07d52009-02-03 20:19:35 +0000174 Tok.is(tok::l_paren), SS,
175 isAddressOfOperand);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000176
Douglas Gregor2def4832008-11-17 20:34:05 +0000177 // We already complained about a bad conversion-function-id,
178 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000179 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000180 }
181
182 } // switch.
183
184 assert(0 && "The switch was supposed to take care everything.");
185}
186
Reid Spencer5f016e22007-07-11 17:01:13 +0000187/// ParseCXXCasts - This handles the various ways to cast expressions to another
188/// type.
189///
190/// postfix-expression: [C++ 5.2p1]
191/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
192/// 'static_cast' '<' type-name '>' '(' expression ')'
193/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
194/// 'const_cast' '<' type-name '>' '(' expression ')'
195///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000196Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000197 tok::TokenKind Kind = Tok.getKind();
198 const char *CastName = 0; // For error messages
199
200 switch (Kind) {
201 default: assert(0 && "Unknown C++ cast!"); abort();
202 case tok::kw_const_cast: CastName = "const_cast"; break;
203 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
204 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
205 case tok::kw_static_cast: CastName = "static_cast"; break;
206 }
207
208 SourceLocation OpLoc = ConsumeToken();
209 SourceLocation LAngleBracketLoc = Tok.getLocation();
210
211 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000212 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000213
Douglas Gregor809070a2009-02-18 17:45:20 +0000214 TypeResult CastTy = ParseTypeName();
Reid Spencer5f016e22007-07-11 17:01:13 +0000215 SourceLocation RAngleBracketLoc = Tok.getLocation();
216
Chris Lattner1ab3b962008-11-18 07:48:38 +0000217 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000218 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000219
220 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
221
Chris Lattner1ab3b962008-11-18 07:48:38 +0000222 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000223 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000224
Sebastian Redld8c4e152008-12-11 22:33:27 +0000225 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000226
Douglas Gregor809070a2009-02-18 17:45:20 +0000227 if (!Result.isInvalid() && !CastTy.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000228 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
Douglas Gregor809070a2009-02-18 17:45:20 +0000229 LAngleBracketLoc, CastTy.get(),
230 RAngleBracketLoc,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000231 LParenLoc, Result.release(), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000232
Sebastian Redl20df9b72008-12-11 22:51:44 +0000233 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000234}
235
Sebastian Redlc42e1182008-11-11 11:37:55 +0000236/// ParseCXXTypeid - This handles the C++ typeid expression.
237///
238/// postfix-expression: [C++ 5.2p1]
239/// 'typeid' '(' expression ')'
240/// 'typeid' '(' type-id ')'
241///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000242Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000243 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
244
245 SourceLocation OpLoc = ConsumeToken();
246 SourceLocation LParenLoc = Tok.getLocation();
247 SourceLocation RParenLoc;
248
249 // typeid expressions are always parenthesized.
250 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
251 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000252 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000253
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000254 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000255
256 if (isTypeIdInParens()) {
Douglas Gregor809070a2009-02-18 17:45:20 +0000257 TypeResult Ty = ParseTypeName();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000258
259 // Match the ')'.
260 MatchRHSPunctuation(tok::r_paren, LParenLoc);
261
Douglas Gregor809070a2009-02-18 17:45:20 +0000262 if (Ty.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000263 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000264
265 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Douglas Gregor809070a2009-02-18 17:45:20 +0000266 Ty.get(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000267 } else {
268 Result = ParseExpression();
269
270 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000271 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000272 SkipUntil(tok::r_paren);
273 else {
274 MatchRHSPunctuation(tok::r_paren, LParenLoc);
275
276 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000277 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000278 }
279 }
280
Sebastian Redl20df9b72008-12-11 22:51:44 +0000281 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000282}
283
Reid Spencer5f016e22007-07-11 17:01:13 +0000284/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
285///
286/// boolean-literal: [C++ 2.13.5]
287/// 'true'
288/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000289Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000290 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000291 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
Reid Spencer5f016e22007-07-11 17:01:13 +0000292}
Chris Lattner50dd2892008-02-26 00:51:44 +0000293
294/// ParseThrowExpression - This handles the C++ throw expression.
295///
296/// throw-expression: [C++ 15]
297/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000298Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000299 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000300 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000301
Chris Lattner2a2819a2008-04-06 06:02:23 +0000302 // If the current token isn't the start of an assignment-expression,
303 // then the expression is not present. This handles things like:
304 // "C ? throw : (void)42", which is crazy but legal.
305 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
306 case tok::semi:
307 case tok::r_paren:
308 case tok::r_square:
309 case tok::r_brace:
310 case tok::colon:
311 case tok::comma:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000312 return Owned(Actions.ActOnCXXThrow(ThrowLoc));
Chris Lattner50dd2892008-02-26 00:51:44 +0000313
Chris Lattner2a2819a2008-04-06 06:02:23 +0000314 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000315 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000316 if (Expr.isInvalid()) return move(Expr);
317 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000318 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000319}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000320
321/// ParseCXXThis - This handles the C++ 'this' pointer.
322///
323/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
324/// a non-lvalue expression whose value is the address of the object for which
325/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000326Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000327 assert(Tok.is(tok::kw_this) && "Not 'this'!");
328 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000329 return Owned(Actions.ActOnCXXThis(ThisLoc));
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000330}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000331
332/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
333/// Can be interpreted either as function-style casting ("int(x)")
334/// or class type construction ("ClassType(x,y,z)")
335/// or creation of a value-initialized type ("int()").
336///
337/// postfix-expression: [C++ 5.2p1]
338/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
339/// typename-specifier '(' expression-list[opt] ')' [TODO]
340///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000341Parser::OwningExprResult
342Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000343 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000344 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000345
346 assert(Tok.is(tok::l_paren) && "Expected '('!");
347 SourceLocation LParenLoc = ConsumeParen();
348
Sebastian Redla55e52c2008-11-25 22:21:31 +0000349 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000350 CommaLocsTy CommaLocs;
351
352 if (Tok.isNot(tok::r_paren)) {
353 if (ParseExpressionList(Exprs, CommaLocs)) {
354 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000355 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000356 }
357 }
358
359 // Match the ')'.
360 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
361
362 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
363 "Unexpected number of commas!");
Sebastian Redl20df9b72008-12-11 22:51:44 +0000364 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
365 LParenLoc,
366 Exprs.take(), Exprs.size(),
367 &CommaLocs[0], RParenLoc));
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000368}
369
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000370/// ParseCXXCondition - if/switch/while/for condition expression.
371///
372/// condition:
373/// expression
374/// type-specifier-seq declarator '=' assignment-expression
375/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
376/// '=' assignment-expression
377///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000378Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000379 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000380 return ParseExpression(); // expression
381
382 SourceLocation StartLoc = Tok.getLocation();
383
384 // type-specifier-seq
385 DeclSpec DS;
386 ParseSpecifierQualifierList(DS);
387
388 // declarator
389 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
390 ParseDeclarator(DeclaratorInfo);
391
392 // simple-asm-expr[opt]
393 if (Tok.is(tok::kw_asm)) {
Sebastian Redlab197ba2009-02-09 18:23:29 +0000394 SourceLocation Loc;
395 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000396 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000397 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000398 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000399 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000400 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000401 DeclaratorInfo.SetRangeEnd(Loc);
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000402 }
403
404 // If attributes are present, parse them.
Sebastian Redlab197ba2009-02-09 18:23:29 +0000405 if (Tok.is(tok::kw___attribute)) {
406 SourceLocation Loc;
407 AttributeList *AttrList = ParseAttributes(&Loc);
408 DeclaratorInfo.AddAttributes(AttrList, Loc);
409 }
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000410
411 // '=' assignment-expression
412 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000413 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000414 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000415 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000416 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000417 return ExprError();
418
419 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
420 DeclaratorInfo,EqualLoc,
421 AssignExpr.release()));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000422}
423
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000424/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
425/// This should only be called when the current token is known to be part of
426/// simple-type-specifier.
427///
428/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000429/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000430/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
431/// char
432/// wchar_t
433/// bool
434/// short
435/// int
436/// long
437/// signed
438/// unsigned
439/// float
440/// double
441/// void
442/// [GNU] typeof-specifier
443/// [C++0x] auto [TODO]
444///
445/// type-name:
446/// class-name
447/// enum-name
448/// typedef-name
449///
450void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
451 DS.SetRangeStart(Tok.getLocation());
452 const char *PrevSpec;
453 SourceLocation Loc = Tok.getLocation();
454
455 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000456 case tok::identifier: // foo::bar
457 case tok::coloncolon: // ::foo::bar
458 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000459 default:
460 assert(0 && "Not a simple-type-specifier token!");
461 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000462
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000463 // type-name
Chris Lattnerb31757b2009-01-06 05:06:21 +0000464 case tok::annot_typename: {
Douglas Gregor1a51b4a2009-02-09 15:09:02 +0000465 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000466 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000467 break;
468 }
469
470 // builtin types
471 case tok::kw_short:
472 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
473 break;
474 case tok::kw_long:
475 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
476 break;
477 case tok::kw_signed:
478 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
479 break;
480 case tok::kw_unsigned:
481 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
482 break;
483 case tok::kw_void:
484 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
485 break;
486 case tok::kw_char:
487 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
488 break;
489 case tok::kw_int:
490 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
491 break;
492 case tok::kw_float:
493 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
494 break;
495 case tok::kw_double:
496 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
497 break;
498 case tok::kw_wchar_t:
499 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
500 break;
501 case tok::kw_bool:
502 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
503 break;
504
505 // GNU typeof support.
506 case tok::kw_typeof:
507 ParseTypeofSpecifier(DS);
508 DS.Finish(Diags, PP.getSourceManager(), getLang());
509 return;
510 }
Chris Lattnerb31757b2009-01-06 05:06:21 +0000511 if (Tok.is(tok::annot_typename))
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000512 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
513 else
514 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000515 ConsumeToken();
516 DS.Finish(Diags, PP.getSourceManager(), getLang());
517}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000518
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000519/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
520/// [dcl.name]), which is a non-empty sequence of type-specifiers,
521/// e.g., "const short int". Note that the DeclSpec is *not* finished
522/// by parsing the type-specifier-seq, because these sequences are
523/// typically followed by some form of declarator. Returns true and
524/// emits diagnostics if this is not a type-specifier-seq, false
525/// otherwise.
526///
527/// type-specifier-seq: [C++ 8.1]
528/// type-specifier type-specifier-seq[opt]
529///
530bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
531 DS.SetRangeStart(Tok.getLocation());
532 const char *PrevSpec = 0;
533 int isInvalid = 0;
534
535 // Parse one or more of the type specifiers.
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000536 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000537 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000538 return true;
539 }
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000540
Ted Kremenekb8006e52009-01-06 19:17:58 +0000541 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000542
543 return false;
544}
545
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000546/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000547/// operator name (C++ [over.oper]). If successful, returns the
548/// predefined identifier that corresponds to that overloaded
549/// operator. Otherwise, returns NULL and does not consume any tokens.
550///
551/// operator-function-id: [C++ 13.5]
552/// 'operator' operator
553///
554/// operator: one of
555/// new delete new[] delete[]
556/// + - * / % ^ & | ~
557/// ! = < > += -= *= /= %=
558/// ^= &= |= << >> >>= <<= == !=
559/// <= >= && || ++ -- , ->* ->
560/// () []
Sebastian Redlab197ba2009-02-09 18:23:29 +0000561OverloadedOperatorKind
562Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000563 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Sebastian Redlab197ba2009-02-09 18:23:29 +0000564 SourceLocation Loc;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000565
566 OverloadedOperatorKind Op = OO_None;
567 switch (NextToken().getKind()) {
568 case tok::kw_new:
569 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000570 Loc = ConsumeToken(); // 'new'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000571 if (Tok.is(tok::l_square)) {
572 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000573 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000574 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
575 Op = OO_Array_New;
576 } else {
577 Op = OO_New;
578 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000579 if (EndLoc)
580 *EndLoc = Loc;
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'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000585 Loc = ConsumeToken(); // 'delete'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000586 if (Tok.is(tok::l_square)) {
587 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000588 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000589 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
590 Op = OO_Array_Delete;
591 } else {
592 Op = OO_Delete;
593 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000594 if (EndLoc)
595 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000596 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000597
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000598#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000599 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000600#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000601#include "clang/Basic/OperatorKinds.def"
602
603 case tok::l_paren:
604 ConsumeToken(); // 'operator'
605 ConsumeParen(); // '('
Sebastian Redlab197ba2009-02-09 18:23:29 +0000606 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000607 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000608 if (EndLoc)
609 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000610 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000611
612 case tok::l_square:
613 ConsumeToken(); // 'operator'
614 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000615 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000616 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000617 if (EndLoc)
618 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000619 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000620
621 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000622 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000623 }
624
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000625 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000626 Loc = ConsumeAnyToken(); // the operator itself
627 if (EndLoc)
628 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000629 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000630}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000631
632/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
633/// which expresses the name of a user-defined conversion operator
634/// (C++ [class.conv.fct]p1). Returns the type that this operator is
635/// specifying a conversion for, or NULL if there was an error.
636///
637/// conversion-function-id: [C++ 12.3.2]
638/// operator conversion-type-id
639///
640/// conversion-type-id:
641/// type-specifier-seq conversion-declarator[opt]
642///
643/// conversion-declarator:
644/// ptr-operator conversion-declarator[opt]
Sebastian Redlab197ba2009-02-09 18:23:29 +0000645Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000646 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
647 ConsumeToken(); // 'operator'
648
649 // Parse the type-specifier-seq.
650 DeclSpec DS;
651 if (ParseCXXTypeSpecifierSeq(DS))
652 return 0;
653
654 // Parse the conversion-declarator, which is merely a sequence of
655 // ptr-operators.
656 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000657 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000658 if (EndLoc)
659 *EndLoc = D.getSourceRange().getEnd();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000660
661 // Finish up the type.
662 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000663 if (Result.isInvalid())
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000664 return 0;
665 else
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000666 return Result.get();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000667}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000668
669/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
670/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000671///
672/// This method is called to parse the new expression after the optional :: has
673/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
674/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000675///
676/// new-expression:
677/// '::'[opt] 'new' new-placement[opt] new-type-id
678/// new-initializer[opt]
679/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
680/// new-initializer[opt]
681///
682/// new-placement:
683/// '(' expression-list ')'
684///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000685/// new-type-id:
686/// type-specifier-seq new-declarator[opt]
687///
688/// new-declarator:
689/// ptr-operator new-declarator[opt]
690/// direct-new-declarator
691///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000692/// new-initializer:
693/// '(' expression-list[opt] ')'
694/// [C++0x] braced-init-list [TODO]
695///
Chris Lattner59232d32009-01-04 21:25:24 +0000696Parser::OwningExprResult
697Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
698 assert(Tok.is(tok::kw_new) && "expected 'new' token");
699 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000700
701 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
702 // second form of new-expression. It can't be a new-type-id.
703
Sebastian Redla55e52c2008-11-25 22:21:31 +0000704 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000705 SourceLocation PlacementLParen, PlacementRParen;
706
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000707 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000708 DeclSpec DS;
709 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000710 if (Tok.is(tok::l_paren)) {
711 // If it turns out to be a placement, we change the type location.
712 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000713 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
714 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000715 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000716 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000717
718 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000719 if (PlacementRParen.isInvalid()) {
720 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000721 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000722 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000723
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000724 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000725 // Reset the placement locations. There was no placement.
726 PlacementLParen = PlacementRParen = SourceLocation();
727 ParenTypeId = true;
728 } else {
729 // We still need the type.
730 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000731 SourceLocation LParen = ConsumeParen();
732 ParseSpecifierQualifierList(DS);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000733 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000734 ParseDeclarator(DeclaratorInfo);
735 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000736 ParenTypeId = true;
737 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000738 if (ParseCXXTypeSpecifierSeq(DS))
739 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000740 else {
741 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000742 ParseDeclaratorInternal(DeclaratorInfo,
743 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000744 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000745 ParenTypeId = false;
746 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000747 }
748 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000749 // A new-type-id is a simplified type-id, where essentially the
750 // direct-declarator is replaced by a direct-new-declarator.
751 if (ParseCXXTypeSpecifierSeq(DS))
752 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000753 else {
754 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000755 ParseDeclaratorInternal(DeclaratorInfo,
756 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000757 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000758 ParenTypeId = false;
759 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000760 if (DeclaratorInfo.getInvalidType()) {
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
Sebastian Redla55e52c2008-11-25 22:21:31 +0000765 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000766 SourceLocation ConstructorLParen, ConstructorRParen;
767
768 if (Tok.is(tok::l_paren)) {
769 ConstructorLParen = ConsumeParen();
770 if (Tok.isNot(tok::r_paren)) {
771 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000772 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
773 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000774 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000775 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000776 }
777 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000778 if (ConstructorRParen.isInvalid()) {
779 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000780 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000781 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000782 }
783
Sebastian Redl20df9b72008-12-11 22:51:44 +0000784 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
785 PlacementArgs.take(), PlacementArgs.size(),
786 PlacementRParen, ParenTypeId, DeclaratorInfo,
787 ConstructorLParen, ConstructorArgs.take(),
788 ConstructorArgs.size(), ConstructorRParen));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000789}
790
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000791/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
792/// passed to ParseDeclaratorInternal.
793///
794/// direct-new-declarator:
795/// '[' expression ']'
796/// direct-new-declarator '[' constant-expression ']'
797///
Chris Lattner59232d32009-01-04 21:25:24 +0000798void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000799 // Parse the array dimensions.
800 bool first = true;
801 while (Tok.is(tok::l_square)) {
802 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000803 OwningExprResult Size(first ? ParseExpression()
804 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000805 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000806 // Recover
807 SkipUntil(tok::r_square);
808 return;
809 }
810 first = false;
811
Sebastian Redlab197ba2009-02-09 18:23:29 +0000812 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000813 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redlab197ba2009-02-09 18:23:29 +0000814 Size.release(), LLoc),
815 RLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000816
Sebastian Redlab197ba2009-02-09 18:23:29 +0000817 if (RLoc.isInvalid())
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000818 return;
819 }
820}
821
822/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
823/// This ambiguity appears in the syntax of the C++ new operator.
824///
825/// new-expression:
826/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
827/// new-initializer[opt]
828///
829/// new-placement:
830/// '(' expression-list ')'
831///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000832bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +0000833 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000834 // The '(' was already consumed.
835 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000836 ParseSpecifierQualifierList(D.getMutableDeclSpec());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000837 D.SetSourceRange(D.getDeclSpec().getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000838 ParseDeclarator(D);
839 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000840 }
841
842 // It's not a type, it has to be an expression list.
843 // Discard the comma locations - ActOnCXXNew has enough parameters.
844 CommaLocsTy CommaLocs;
845 return ParseExpressionList(PlacementArgs, CommaLocs);
846}
847
848/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
849/// to free memory allocated by new.
850///
Chris Lattner59232d32009-01-04 21:25:24 +0000851/// This method is called to parse the 'delete' expression after the optional
852/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
853/// and "Start" is its location. Otherwise, "Start" is the location of the
854/// 'delete' token.
855///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000856/// delete-expression:
857/// '::'[opt] 'delete' cast-expression
858/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +0000859Parser::OwningExprResult
860Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
861 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
862 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000863
864 // Array delete?
865 bool ArrayDelete = false;
866 if (Tok.is(tok::l_square)) {
867 ArrayDelete = true;
868 SourceLocation LHS = ConsumeBracket();
869 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
870 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000871 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000872 }
873
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000874 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000875 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000876 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000877
Sebastian Redl20df9b72008-12-11 22:51:44 +0000878 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
879 Operand.release()));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000880}
Sebastian Redl64b45f72009-01-05 20:52:13 +0000881
882static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
883{
884 switch(kind) {
885 default: assert(false && "Not a known unary type trait.");
886 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
887 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
888 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
889 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
890 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
891 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
892 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
893 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
894 case tok::kw___is_abstract: return UTT_IsAbstract;
895 case tok::kw___is_class: return UTT_IsClass;
896 case tok::kw___is_empty: return UTT_IsEmpty;
897 case tok::kw___is_enum: return UTT_IsEnum;
898 case tok::kw___is_pod: return UTT_IsPOD;
899 case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
900 case tok::kw___is_union: return UTT_IsUnion;
901 }
902}
903
904/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
905/// pseudo-functions that allow implementation of the TR1/C++0x type traits
906/// templates.
907///
908/// primary-expression:
909/// [GNU] unary-type-trait '(' type-id ')'
910///
911Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
912{
913 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
914 SourceLocation Loc = ConsumeToken();
915
916 SourceLocation LParen = Tok.getLocation();
917 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
918 return ExprError();
919
920 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
921 // there will be cryptic errors about mismatched parentheses and missing
922 // specifiers.
Douglas Gregor809070a2009-02-18 17:45:20 +0000923 TypeResult Ty = ParseTypeName();
Sebastian Redl64b45f72009-01-05 20:52:13 +0000924
925 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
926
Douglas Gregor809070a2009-02-18 17:45:20 +0000927 if (Ty.isInvalid())
928 return ExprError();
929
930 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
Sebastian Redl64b45f72009-01-05 20:52:13 +0000931}