blob: b0ce072a415aba704de10ab7fb27635fc87d6734 [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.
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000022///
23/// '::'[opt] nested-name-specifier
24/// '::'
25///
26/// nested-name-specifier:
27/// type-name '::'
28/// namespace-name '::'
29/// nested-name-specifier identifier '::'
30/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
31///
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000032bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS) {
33 assert(getLang().CPlusPlus &&
34 "Call sites of this function should be guarded by checking for C++.");
35
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000036 if (Tok.is(tok::annot_cxxscope)) {
37 SS.setScopeRep(Tok.getAnnotationValue());
38 SS.setRange(Tok.getAnnotationRange());
39 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000040 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000041 }
Chris Lattnere607e802009-01-04 21:14:15 +000042
43 if (Tok.isNot(tok::coloncolon) &&
44 (Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon)))
45 return false;
46
47 // ::new and ::delete aren't nested-name-specifiers, so parsing the :: as
48 // a scope specifier only makes things more complicated.
49 if (Tok.is(tok::coloncolon)) {
50 Token Next = NextToken();
51 if (Next.is(tok::kw_new) || Next.is(tok::kw_delete))
52 return false;
53 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000054
55 SS.setBeginLoc(Tok.getLocation());
56
57 // '::'
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000058 if (Tok.is(tok::coloncolon)) {
59 // Global scope.
60 SourceLocation CCLoc = ConsumeToken();
61 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
62 SS.setEndLoc(CCLoc);
63 }
64
65 // nested-name-specifier:
66 // type-name '::'
67 // namespace-name '::'
68 // nested-name-specifier identifier '::'
69 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000070 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
71 IdentifierInfo *II = Tok.getIdentifierInfo();
72 SourceLocation IdLoc = ConsumeToken();
Chris Lattnere607e802009-01-04 21:14:15 +000073 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000074 SourceLocation CCLoc = ConsumeToken();
75 if (SS.isInvalid())
76 continue;
77
78 SS.setScopeRep(
Chris Lattnere607e802009-01-04 21:14:15 +000079 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000080 SS.setEndLoc(CCLoc);
81 }
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000082
83 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000084}
85
86/// ParseCXXIdExpression - Handle id-expression.
87///
88/// id-expression:
89/// unqualified-id
90/// qualified-id
91///
92/// unqualified-id:
93/// identifier
94/// operator-function-id
95/// conversion-function-id [TODO]
96/// '~' class-name [TODO]
97/// template-id [TODO]
98///
99/// qualified-id:
100/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
101/// '::' identifier
102/// '::' operator-function-id
103/// '::' template-id [TODO]
104///
105/// nested-name-specifier:
106/// type-name '::'
107/// namespace-name '::'
108/// nested-name-specifier identifier '::'
109/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
110///
111/// NOTE: The standard specifies that, for qualified-id, the parser does not
112/// expect:
113///
114/// '::' conversion-function-id
115/// '::' '~' class-name
116///
117/// This may cause a slight inconsistency on diagnostics:
118///
119/// class C {};
120/// namespace A {}
121/// void f() {
122/// :: A :: ~ C(); // Some Sema error about using destructor with a
123/// // namespace.
124/// :: ~ C(); // Some Parser error like 'unexpected ~'.
125/// }
126///
127/// We simplify the parser a bit and make it work like:
128///
129/// qualified-id:
130/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
131/// '::' unqualified-id
132///
133/// That way Sema can handle and report similar errors for namespaces and the
134/// global scope.
135///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000136Parser::OwningExprResult Parser::ParseCXXIdExpression() {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000137 // qualified-id:
138 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
139 // '::' unqualified-id
140 //
141 CXXScopeSpec SS;
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000142 MaybeParseCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000143
144 // unqualified-id:
145 // identifier
146 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000147 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000148 // '~' class-name [TODO]
149 // template-id [TODO]
150 //
151 switch (Tok.getKind()) {
152 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000153 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000154
155 case tok::identifier: {
156 // Consume the identifier so that we can see if it is followed by a '('.
157 IdentifierInfo &II = *Tok.getIdentifierInfo();
158 SourceLocation L = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000159 return Owned(Actions.ActOnIdentifierExpr(CurScope, L, II,
160 Tok.is(tok::l_paren), &SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000161 }
162
163 case tok::kw_operator: {
164 SourceLocation OperatorLoc = Tok.getLocation();
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000165 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
Sebastian Redl20df9b72008-12-11 22:51:44 +0000166 return Owned(Actions.ActOnCXXOperatorFunctionIdExpr(
167 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS));
Douglas Gregor2def4832008-11-17 20:34:05 +0000168 } else if (TypeTy *Type = ParseConversionFunctionId()) {
Sebastian Redl20df9b72008-12-11 22:51:44 +0000169 return Owned(Actions.ActOnCXXConversionFunctionExpr(
170 CurScope, OperatorLoc, Type, Tok.is(tok::l_paren),SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000171 }
Sebastian Redl20df9b72008-12-11 22:51:44 +0000172
Douglas Gregor2def4832008-11-17 20:34:05 +0000173 // We already complained about a bad conversion-function-id,
174 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000175 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000176 }
177
178 } // switch.
179
180 assert(0 && "The switch was supposed to take care everything.");
181}
182
Reid Spencer5f016e22007-07-11 17:01:13 +0000183/// ParseCXXCasts - This handles the various ways to cast expressions to another
184/// type.
185///
186/// postfix-expression: [C++ 5.2p1]
187/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
188/// 'static_cast' '<' type-name '>' '(' expression ')'
189/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
190/// 'const_cast' '<' type-name '>' '(' expression ')'
191///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000192Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000193 tok::TokenKind Kind = Tok.getKind();
194 const char *CastName = 0; // For error messages
195
196 switch (Kind) {
197 default: assert(0 && "Unknown C++ cast!"); abort();
198 case tok::kw_const_cast: CastName = "const_cast"; break;
199 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
200 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
201 case tok::kw_static_cast: CastName = "static_cast"; break;
202 }
203
204 SourceLocation OpLoc = ConsumeToken();
205 SourceLocation LAngleBracketLoc = Tok.getLocation();
206
207 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000208 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000209
210 TypeTy *CastTy = ParseTypeName();
211 SourceLocation RAngleBracketLoc = Tok.getLocation();
212
Chris Lattner1ab3b962008-11-18 07:48:38 +0000213 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000214 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000215
216 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
217
Chris Lattner1ab3b962008-11-18 07:48:38 +0000218 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000219 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000220
Sebastian Redld8c4e152008-12-11 22:33:27 +0000221 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000222
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000223 if (!Result.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000224 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
225 LAngleBracketLoc, CastTy, RAngleBracketLoc,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000226 LParenLoc, Result.release(), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000227
Sebastian Redl20df9b72008-12-11 22:51:44 +0000228 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000229}
230
Sebastian Redlc42e1182008-11-11 11:37:55 +0000231/// ParseCXXTypeid - This handles the C++ typeid expression.
232///
233/// postfix-expression: [C++ 5.2p1]
234/// 'typeid' '(' expression ')'
235/// 'typeid' '(' type-id ')'
236///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000237Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000238 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
239
240 SourceLocation OpLoc = ConsumeToken();
241 SourceLocation LParenLoc = Tok.getLocation();
242 SourceLocation RParenLoc;
243
244 // typeid expressions are always parenthesized.
245 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
246 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000247 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000248
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000249 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000250
251 if (isTypeIdInParens()) {
252 TypeTy *Ty = ParseTypeName();
253
254 // Match the ')'.
255 MatchRHSPunctuation(tok::r_paren, LParenLoc);
256
257 if (!Ty)
Sebastian Redl20df9b72008-12-11 22:51:44 +0000258 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000259
260 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
261 Ty, RParenLoc);
262 } else {
263 Result = ParseExpression();
264
265 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000266 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000267 SkipUntil(tok::r_paren);
268 else {
269 MatchRHSPunctuation(tok::r_paren, LParenLoc);
270
271 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000272 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000273 }
274 }
275
Sebastian Redl20df9b72008-12-11 22:51:44 +0000276 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000277}
278
Reid Spencer5f016e22007-07-11 17:01:13 +0000279/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
280///
281/// boolean-literal: [C++ 2.13.5]
282/// 'true'
283/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000284Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000285 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000286 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
Reid Spencer5f016e22007-07-11 17:01:13 +0000287}
Chris Lattner50dd2892008-02-26 00:51:44 +0000288
289/// ParseThrowExpression - This handles the C++ throw expression.
290///
291/// throw-expression: [C++ 15]
292/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000293Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000294 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000295 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000296
Chris Lattner2a2819a2008-04-06 06:02:23 +0000297 // If the current token isn't the start of an assignment-expression,
298 // then the expression is not present. This handles things like:
299 // "C ? throw : (void)42", which is crazy but legal.
300 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
301 case tok::semi:
302 case tok::r_paren:
303 case tok::r_square:
304 case tok::r_brace:
305 case tok::colon:
306 case tok::comma:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000307 return Owned(Actions.ActOnCXXThrow(ThrowLoc));
Chris Lattner50dd2892008-02-26 00:51:44 +0000308
Chris Lattner2a2819a2008-04-06 06:02:23 +0000309 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000310 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000311 if (Expr.isInvalid()) return move(Expr);
312 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000313 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000314}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000315
316/// ParseCXXThis - This handles the C++ 'this' pointer.
317///
318/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
319/// a non-lvalue expression whose value is the address of the object for which
320/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000321Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000322 assert(Tok.is(tok::kw_this) && "Not 'this'!");
323 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000324 return Owned(Actions.ActOnCXXThis(ThisLoc));
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000325}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000326
327/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
328/// Can be interpreted either as function-style casting ("int(x)")
329/// or class type construction ("ClassType(x,y,z)")
330/// or creation of a value-initialized type ("int()").
331///
332/// postfix-expression: [C++ 5.2p1]
333/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
334/// typename-specifier '(' expression-list[opt] ')' [TODO]
335///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000336Parser::OwningExprResult
337Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000338 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
339 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
340
341 assert(Tok.is(tok::l_paren) && "Expected '('!");
342 SourceLocation LParenLoc = ConsumeParen();
343
Sebastian Redla55e52c2008-11-25 22:21:31 +0000344 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000345 CommaLocsTy CommaLocs;
346
347 if (Tok.isNot(tok::r_paren)) {
348 if (ParseExpressionList(Exprs, CommaLocs)) {
349 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000350 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000351 }
352 }
353
354 // Match the ')'.
355 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
356
357 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
358 "Unexpected number of commas!");
Sebastian Redl20df9b72008-12-11 22:51:44 +0000359 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
360 LParenLoc,
361 Exprs.take(), Exprs.size(),
362 &CommaLocs[0], RParenLoc));
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000363}
364
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000365/// ParseCXXCondition - if/switch/while/for condition expression.
366///
367/// condition:
368/// expression
369/// type-specifier-seq declarator '=' assignment-expression
370/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
371/// '=' assignment-expression
372///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000373Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000374 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000375 return ParseExpression(); // expression
376
377 SourceLocation StartLoc = Tok.getLocation();
378
379 // type-specifier-seq
380 DeclSpec DS;
381 ParseSpecifierQualifierList(DS);
382
383 // declarator
384 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
385 ParseDeclarator(DeclaratorInfo);
386
387 // simple-asm-expr[opt]
388 if (Tok.is(tok::kw_asm)) {
Sebastian Redleffa8d12008-12-10 00:02:53 +0000389 OwningExprResult AsmLabel(ParseSimpleAsm());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000390 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000391 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000392 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000393 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000394 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000395 }
396
397 // If attributes are present, parse them.
398 if (Tok.is(tok::kw___attribute))
399 DeclaratorInfo.AddAttributes(ParseAttributes());
400
401 // '=' assignment-expression
402 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000403 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000404 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000405 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000406 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000407 return ExprError();
408
409 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
410 DeclaratorInfo,EqualLoc,
411 AssignExpr.release()));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000412}
413
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000414/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
415/// This should only be called when the current token is known to be part of
416/// simple-type-specifier.
417///
418/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000419/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000420/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
421/// char
422/// wchar_t
423/// bool
424/// short
425/// int
426/// long
427/// signed
428/// unsigned
429/// float
430/// double
431/// void
432/// [GNU] typeof-specifier
433/// [C++0x] auto [TODO]
434///
435/// type-name:
436/// class-name
437/// enum-name
438/// typedef-name
439///
440void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000441 // Annotate typenames and C++ scope specifiers.
442 TryAnnotateTypeOrScopeToken();
443
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000444 DS.SetRangeStart(Tok.getLocation());
445 const char *PrevSpec;
446 SourceLocation Loc = Tok.getLocation();
447
448 switch (Tok.getKind()) {
449 default:
450 assert(0 && "Not a simple-type-specifier token!");
451 abort();
452
453 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000454 case tok::annot_qualtypename: {
455 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
456 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000457 break;
458 }
459
460 // builtin types
461 case tok::kw_short:
462 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
463 break;
464 case tok::kw_long:
465 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
466 break;
467 case tok::kw_signed:
468 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
469 break;
470 case tok::kw_unsigned:
471 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
472 break;
473 case tok::kw_void:
474 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
475 break;
476 case tok::kw_char:
477 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
478 break;
479 case tok::kw_int:
480 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
481 break;
482 case tok::kw_float:
483 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
484 break;
485 case tok::kw_double:
486 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
487 break;
488 case tok::kw_wchar_t:
489 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
490 break;
491 case tok::kw_bool:
492 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
493 break;
494
495 // GNU typeof support.
496 case tok::kw_typeof:
497 ParseTypeofSpecifier(DS);
498 DS.Finish(Diags, PP.getSourceManager(), getLang());
499 return;
500 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000501 if (Tok.is(tok::annot_qualtypename))
502 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
503 else
504 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000505 ConsumeToken();
506 DS.Finish(Diags, PP.getSourceManager(), getLang());
507}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000508
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000509/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
510/// [dcl.name]), which is a non-empty sequence of type-specifiers,
511/// e.g., "const short int". Note that the DeclSpec is *not* finished
512/// by parsing the type-specifier-seq, because these sequences are
513/// typically followed by some form of declarator. Returns true and
514/// emits diagnostics if this is not a type-specifier-seq, false
515/// otherwise.
516///
517/// type-specifier-seq: [C++ 8.1]
518/// type-specifier type-specifier-seq[opt]
519///
520bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
521 DS.SetRangeStart(Tok.getLocation());
522 const char *PrevSpec = 0;
523 int isInvalid = 0;
524
525 // Parse one or more of the type specifiers.
526 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000527 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000528 return true;
529 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000530 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000531
532 return false;
533}
534
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000535/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000536/// operator name (C++ [over.oper]). If successful, returns the
537/// predefined identifier that corresponds to that overloaded
538/// operator. Otherwise, returns NULL and does not consume any tokens.
539///
540/// operator-function-id: [C++ 13.5]
541/// 'operator' operator
542///
543/// operator: one of
544/// new delete new[] delete[]
545/// + - * / % ^ & | ~
546/// ! = < > += -= *= /= %=
547/// ^= &= |= << >> >>= <<= == !=
548/// <= >= && || ++ -- , ->* ->
549/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000550OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000551 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000552
553 OverloadedOperatorKind Op = OO_None;
554 switch (NextToken().getKind()) {
555 case tok::kw_new:
556 ConsumeToken(); // 'operator'
557 ConsumeToken(); // 'new'
558 if (Tok.is(tok::l_square)) {
559 ConsumeBracket(); // '['
560 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
561 Op = OO_Array_New;
562 } else {
563 Op = OO_New;
564 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000565 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000566
567 case tok::kw_delete:
568 ConsumeToken(); // 'operator'
569 ConsumeToken(); // 'delete'
570 if (Tok.is(tok::l_square)) {
571 ConsumeBracket(); // '['
572 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
573 Op = OO_Array_Delete;
574 } else {
575 Op = OO_Delete;
576 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000577 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000578
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000579#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000580 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000581#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000582#include "clang/Basic/OperatorKinds.def"
583
584 case tok::l_paren:
585 ConsumeToken(); // 'operator'
586 ConsumeParen(); // '('
587 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000588 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000589
590 case tok::l_square:
591 ConsumeToken(); // 'operator'
592 ConsumeBracket(); // '['
593 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000594 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000595
596 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000597 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000598 }
599
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000600 ConsumeToken(); // 'operator'
601 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000602 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000603}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000604
605/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
606/// which expresses the name of a user-defined conversion operator
607/// (C++ [class.conv.fct]p1). Returns the type that this operator is
608/// specifying a conversion for, or NULL if there was an error.
609///
610/// conversion-function-id: [C++ 12.3.2]
611/// operator conversion-type-id
612///
613/// conversion-type-id:
614/// type-specifier-seq conversion-declarator[opt]
615///
616/// conversion-declarator:
617/// ptr-operator conversion-declarator[opt]
618Parser::TypeTy *Parser::ParseConversionFunctionId() {
619 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
620 ConsumeToken(); // 'operator'
621
622 // Parse the type-specifier-seq.
623 DeclSpec DS;
624 if (ParseCXXTypeSpecifierSeq(DS))
625 return 0;
626
627 // Parse the conversion-declarator, which is merely a sequence of
628 // ptr-operators.
629 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000630 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000631
632 // Finish up the type.
633 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
634 if (Result.isInvalid)
635 return 0;
636 else
637 return Result.Val;
638}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000639
640/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
641/// memory in a typesafe manner and call constructors.
642///
643/// new-expression:
644/// '::'[opt] 'new' new-placement[opt] new-type-id
645/// new-initializer[opt]
646/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
647/// new-initializer[opt]
648///
649/// new-placement:
650/// '(' expression-list ')'
651///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000652/// new-type-id:
653/// type-specifier-seq new-declarator[opt]
654///
655/// new-declarator:
656/// ptr-operator new-declarator[opt]
657/// direct-new-declarator
658///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000659/// new-initializer:
660/// '(' expression-list[opt] ')'
661/// [C++0x] braced-init-list [TODO]
662///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000663Parser::OwningExprResult Parser::ParseCXXNewExpression()
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000664{
665 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_new)) &&
666 "Expected :: or 'new' keyword");
667
668 SourceLocation Start = Tok.getLocation();
669 bool UseGlobal = false;
670 if (Tok.is(tok::coloncolon)) {
671 UseGlobal = true;
672 ConsumeToken();
673 }
674
675 assert(Tok.is(tok::kw_new) && "Lookahead should have ensured 'new'");
676 // Consume 'new'
677 ConsumeToken();
678
679 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
680 // second form of new-expression. It can't be a new-type-id.
681
Sebastian Redla55e52c2008-11-25 22:21:31 +0000682 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000683 SourceLocation PlacementLParen, PlacementRParen;
684
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000685 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000686 DeclSpec DS;
687 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000688 if (Tok.is(tok::l_paren)) {
689 // If it turns out to be a placement, we change the type location.
690 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000691 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
692 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000693 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000694 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000695
696 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000697 if (PlacementRParen.isInvalid()) {
698 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000699 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000700 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000701
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000702 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000703 // Reset the placement locations. There was no placement.
704 PlacementLParen = PlacementRParen = SourceLocation();
705 ParenTypeId = true;
706 } else {
707 // We still need the type.
708 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000709 SourceLocation LParen = ConsumeParen();
710 ParseSpecifierQualifierList(DS);
711 ParseDeclarator(DeclaratorInfo);
712 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000713 ParenTypeId = true;
714 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000715 if (ParseCXXTypeSpecifierSeq(DS))
716 DeclaratorInfo.setInvalidType(true);
717 else
718 ParseDeclaratorInternal(DeclaratorInfo,
719 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000720 ParenTypeId = false;
721 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000722 }
723 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000724 // A new-type-id is a simplified type-id, where essentially the
725 // direct-declarator is replaced by a direct-new-declarator.
726 if (ParseCXXTypeSpecifierSeq(DS))
727 DeclaratorInfo.setInvalidType(true);
728 else
729 ParseDeclaratorInternal(DeclaratorInfo,
730 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000731 ParenTypeId = false;
732 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000733 if (DeclaratorInfo.getInvalidType()) {
734 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000735 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000736 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000737
Sebastian Redla55e52c2008-11-25 22:21:31 +0000738 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000739 SourceLocation ConstructorLParen, ConstructorRParen;
740
741 if (Tok.is(tok::l_paren)) {
742 ConstructorLParen = ConsumeParen();
743 if (Tok.isNot(tok::r_paren)) {
744 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000745 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
746 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000747 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000748 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000749 }
750 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000751 if (ConstructorRParen.isInvalid()) {
752 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000753 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000754 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000755 }
756
Sebastian Redl20df9b72008-12-11 22:51:44 +0000757 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
758 PlacementArgs.take(), PlacementArgs.size(),
759 PlacementRParen, ParenTypeId, DeclaratorInfo,
760 ConstructorLParen, ConstructorArgs.take(),
761 ConstructorArgs.size(), ConstructorRParen));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000762}
763
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000764/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
765/// passed to ParseDeclaratorInternal.
766///
767/// direct-new-declarator:
768/// '[' expression ']'
769/// direct-new-declarator '[' constant-expression ']'
770///
771void Parser::ParseDirectNewDeclarator(Declarator &D)
772{
773 // Parse the array dimensions.
774 bool first = true;
775 while (Tok.is(tok::l_square)) {
776 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000777 OwningExprResult Size(first ? ParseExpression()
778 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000779 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000780 // Recover
781 SkipUntil(tok::r_square);
782 return;
783 }
784 first = false;
785
786 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000787 Size.release(), LLoc));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000788
789 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
790 return;
791 }
792}
793
794/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
795/// This ambiguity appears in the syntax of the C++ new operator.
796///
797/// new-expression:
798/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
799/// new-initializer[opt]
800///
801/// new-placement:
802/// '(' expression-list ')'
803///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000804bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
805 Declarator &D)
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000806{
807 // The '(' was already consumed.
808 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000809 ParseSpecifierQualifierList(D.getMutableDeclSpec());
810 ParseDeclarator(D);
811 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000812 }
813
814 // It's not a type, it has to be an expression list.
815 // Discard the comma locations - ActOnCXXNew has enough parameters.
816 CommaLocsTy CommaLocs;
817 return ParseExpressionList(PlacementArgs, CommaLocs);
818}
819
820/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
821/// to free memory allocated by new.
822///
823/// delete-expression:
824/// '::'[opt] 'delete' cast-expression
825/// '::'[opt] 'delete' '[' ']' cast-expression
Sebastian Redl20df9b72008-12-11 22:51:44 +0000826Parser::OwningExprResult Parser::ParseCXXDeleteExpression()
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000827{
828 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_delete)) &&
829 "Expected :: or 'delete' keyword");
830
831 SourceLocation Start = Tok.getLocation();
832 bool UseGlobal = false;
833 if (Tok.is(tok::coloncolon)) {
834 UseGlobal = true;
835 ConsumeToken();
836 }
837
838 assert(Tok.is(tok::kw_delete) && "Lookahead should have ensured 'delete'");
839 // Consume 'delete'
840 ConsumeToken();
841
842 // Array delete?
843 bool ArrayDelete = false;
844 if (Tok.is(tok::l_square)) {
845 ArrayDelete = true;
846 SourceLocation LHS = ConsumeBracket();
847 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
848 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000849 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000850 }
851
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000852 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000853 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000854 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000855
Sebastian Redl20df9b72008-12-11 22:51:44 +0000856 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
857 Operand.release()));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000858}