blob: 5da39bae07d3263e365ce8ec567e943152df10a3 [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
36 if (Tok.isNot(tok::coloncolon) &&
37 Tok.isNot(tok::annot_cxxscope) &&
38 (Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon)))
39 return false;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000040
Zhongxing Xu00c028b2008-12-08 05:12:38 +000041 // ::new and ::delete aren't nested-name-specifiers, so parsing the :: as
Sebastian Redlbcf293b2008-12-02 17:10:24 +000042 // a scope specifier only makes things more complicated.
Sebastian Redlfb4ccd72008-12-02 16:35:44 +000043 if (Tok.is(tok::coloncolon) && (NextToken().is(tok::kw_new) ||
44 NextToken().is(tok::kw_delete)))
45 return false;
46
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000047 if (Tok.is(tok::annot_cxxscope)) {
48 SS.setScopeRep(Tok.getAnnotationValue());
49 SS.setRange(Tok.getAnnotationRange());
50 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000051 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000052 }
53
54 SS.setBeginLoc(Tok.getLocation());
55
56 // '::'
57
58 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]
70
71 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
72 IdentifierInfo *II = Tok.getIdentifierInfo();
73 SourceLocation IdLoc = ConsumeToken();
74 assert(Tok.is(tok::coloncolon) &&
75 "NextToken() not working properly!");
76 SourceLocation CCLoc = ConsumeToken();
77 if (SS.isInvalid())
78 continue;
79
80 SS.setScopeRep(
81 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II) );
82 SS.setEndLoc(CCLoc);
83 }
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000084
85 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000086}
87
88/// ParseCXXIdExpression - Handle id-expression.
89///
90/// id-expression:
91/// unqualified-id
92/// qualified-id
93///
94/// unqualified-id:
95/// identifier
96/// operator-function-id
97/// conversion-function-id [TODO]
98/// '~' class-name [TODO]
99/// template-id [TODO]
100///
101/// qualified-id:
102/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
103/// '::' identifier
104/// '::' operator-function-id
105/// '::' template-id [TODO]
106///
107/// nested-name-specifier:
108/// type-name '::'
109/// namespace-name '::'
110/// nested-name-specifier identifier '::'
111/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
112///
113/// NOTE: The standard specifies that, for qualified-id, the parser does not
114/// expect:
115///
116/// '::' conversion-function-id
117/// '::' '~' class-name
118///
119/// This may cause a slight inconsistency on diagnostics:
120///
121/// class C {};
122/// namespace A {}
123/// void f() {
124/// :: A :: ~ C(); // Some Sema error about using destructor with a
125/// // namespace.
126/// :: ~ C(); // Some Parser error like 'unexpected ~'.
127/// }
128///
129/// We simplify the parser a bit and make it work like:
130///
131/// qualified-id:
132/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
133/// '::' unqualified-id
134///
135/// That way Sema can handle and report similar errors for namespaces and the
136/// global scope.
137///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000138Parser::OwningExprResult Parser::ParseCXXIdExpression() {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000139 // qualified-id:
140 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
141 // '::' unqualified-id
142 //
143 CXXScopeSpec SS;
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000144 MaybeParseCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000145
146 // unqualified-id:
147 // identifier
148 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000149 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000150 // '~' class-name [TODO]
151 // template-id [TODO]
152 //
153 switch (Tok.getKind()) {
154 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000155 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000156
157 case tok::identifier: {
158 // Consume the identifier so that we can see if it is followed by a '('.
159 IdentifierInfo &II = *Tok.getIdentifierInfo();
160 SourceLocation L = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000161 return Owned(Actions.ActOnIdentifierExpr(CurScope, L, II,
162 Tok.is(tok::l_paren), &SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000163 }
164
165 case tok::kw_operator: {
166 SourceLocation OperatorLoc = Tok.getLocation();
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000167 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
Sebastian Redl20df9b72008-12-11 22:51:44 +0000168 return Owned(Actions.ActOnCXXOperatorFunctionIdExpr(
169 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS));
Douglas Gregor2def4832008-11-17 20:34:05 +0000170 } else if (TypeTy *Type = ParseConversionFunctionId()) {
Sebastian Redl20df9b72008-12-11 22:51:44 +0000171 return Owned(Actions.ActOnCXXConversionFunctionExpr(
172 CurScope, OperatorLoc, Type, Tok.is(tok::l_paren),SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000173 }
Sebastian Redl20df9b72008-12-11 22:51:44 +0000174
Douglas Gregor2def4832008-11-17 20:34:05 +0000175 // We already complained about a bad conversion-function-id,
176 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000177 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000178 }
179
180 } // switch.
181
182 assert(0 && "The switch was supposed to take care everything.");
183}
184
Reid Spencer5f016e22007-07-11 17:01:13 +0000185/// ParseCXXCasts - This handles the various ways to cast expressions to another
186/// type.
187///
188/// postfix-expression: [C++ 5.2p1]
189/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
190/// 'static_cast' '<' type-name '>' '(' expression ')'
191/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
192/// 'const_cast' '<' type-name '>' '(' expression ')'
193///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000194Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000195 tok::TokenKind Kind = Tok.getKind();
196 const char *CastName = 0; // For error messages
197
198 switch (Kind) {
199 default: assert(0 && "Unknown C++ cast!"); abort();
200 case tok::kw_const_cast: CastName = "const_cast"; break;
201 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
202 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
203 case tok::kw_static_cast: CastName = "static_cast"; break;
204 }
205
206 SourceLocation OpLoc = ConsumeToken();
207 SourceLocation LAngleBracketLoc = Tok.getLocation();
208
209 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000210 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000211
212 TypeTy *CastTy = ParseTypeName();
213 SourceLocation RAngleBracketLoc = Tok.getLocation();
214
Chris Lattner1ab3b962008-11-18 07:48:38 +0000215 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000216 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000217
218 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
219
Chris Lattner1ab3b962008-11-18 07:48:38 +0000220 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000221 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000222
Sebastian Redld8c4e152008-12-11 22:33:27 +0000223 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000224
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000225 if (!Result.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000226 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
227 LAngleBracketLoc, CastTy, RAngleBracketLoc,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000228 LParenLoc, Result.release(), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000229
Sebastian Redl20df9b72008-12-11 22:51:44 +0000230 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000231}
232
Sebastian Redlc42e1182008-11-11 11:37:55 +0000233/// ParseCXXTypeid - This handles the C++ typeid expression.
234///
235/// postfix-expression: [C++ 5.2p1]
236/// 'typeid' '(' expression ')'
237/// 'typeid' '(' type-id ')'
238///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000239Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000240 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
241
242 SourceLocation OpLoc = ConsumeToken();
243 SourceLocation LParenLoc = Tok.getLocation();
244 SourceLocation RParenLoc;
245
246 // typeid expressions are always parenthesized.
247 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
248 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000249 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000250
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000251 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000252
253 if (isTypeIdInParens()) {
254 TypeTy *Ty = ParseTypeName();
255
256 // Match the ')'.
257 MatchRHSPunctuation(tok::r_paren, LParenLoc);
258
259 if (!Ty)
Sebastian Redl20df9b72008-12-11 22:51:44 +0000260 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000261
262 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
263 Ty, RParenLoc);
264 } else {
265 Result = ParseExpression();
266
267 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000268 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000269 SkipUntil(tok::r_paren);
270 else {
271 MatchRHSPunctuation(tok::r_paren, LParenLoc);
272
273 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000274 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000275 }
276 }
277
Sebastian Redl20df9b72008-12-11 22:51:44 +0000278 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000279}
280
Reid Spencer5f016e22007-07-11 17:01:13 +0000281/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
282///
283/// boolean-literal: [C++ 2.13.5]
284/// 'true'
285/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000286Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000287 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000288 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
Reid Spencer5f016e22007-07-11 17:01:13 +0000289}
Chris Lattner50dd2892008-02-26 00:51:44 +0000290
291/// ParseThrowExpression - This handles the C++ throw expression.
292///
293/// throw-expression: [C++ 15]
294/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000295Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000296 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000297 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000298
Chris Lattner2a2819a2008-04-06 06:02:23 +0000299 // If the current token isn't the start of an assignment-expression,
300 // then the expression is not present. This handles things like:
301 // "C ? throw : (void)42", which is crazy but legal.
302 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
303 case tok::semi:
304 case tok::r_paren:
305 case tok::r_square:
306 case tok::r_brace:
307 case tok::colon:
308 case tok::comma:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000309 return Owned(Actions.ActOnCXXThrow(ThrowLoc));
Chris Lattner50dd2892008-02-26 00:51:44 +0000310
Chris Lattner2a2819a2008-04-06 06:02:23 +0000311 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000312 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000313 if (Expr.isInvalid()) return move(Expr);
314 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000315 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000316}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000317
318/// ParseCXXThis - This handles the C++ 'this' pointer.
319///
320/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
321/// a non-lvalue expression whose value is the address of the object for which
322/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000323Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000324 assert(Tok.is(tok::kw_this) && "Not 'this'!");
325 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000326 return Owned(Actions.ActOnCXXThis(ThisLoc));
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000327}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000328
329/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
330/// Can be interpreted either as function-style casting ("int(x)")
331/// or class type construction ("ClassType(x,y,z)")
332/// or creation of a value-initialized type ("int()").
333///
334/// postfix-expression: [C++ 5.2p1]
335/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
336/// typename-specifier '(' expression-list[opt] ')' [TODO]
337///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000338Parser::OwningExprResult
339Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000340 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
341 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
342
343 assert(Tok.is(tok::l_paren) && "Expected '('!");
344 SourceLocation LParenLoc = ConsumeParen();
345
Sebastian Redla55e52c2008-11-25 22:21:31 +0000346 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000347 CommaLocsTy CommaLocs;
348
349 if (Tok.isNot(tok::r_paren)) {
350 if (ParseExpressionList(Exprs, CommaLocs)) {
351 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000352 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000353 }
354 }
355
356 // Match the ')'.
357 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
358
359 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
360 "Unexpected number of commas!");
Sebastian Redl20df9b72008-12-11 22:51:44 +0000361 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
362 LParenLoc,
363 Exprs.take(), Exprs.size(),
364 &CommaLocs[0], RParenLoc));
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000365}
366
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000367/// ParseCXXCondition - if/switch/while/for condition expression.
368///
369/// condition:
370/// expression
371/// type-specifier-seq declarator '=' assignment-expression
372/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
373/// '=' assignment-expression
374///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000375Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000376 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000377 return ParseExpression(); // expression
378
379 SourceLocation StartLoc = Tok.getLocation();
380
381 // type-specifier-seq
382 DeclSpec DS;
383 ParseSpecifierQualifierList(DS);
384
385 // declarator
386 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
387 ParseDeclarator(DeclaratorInfo);
388
389 // simple-asm-expr[opt]
390 if (Tok.is(tok::kw_asm)) {
Sebastian Redleffa8d12008-12-10 00:02:53 +0000391 OwningExprResult AsmLabel(ParseSimpleAsm());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000392 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000393 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000394 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000395 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000396 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000397 }
398
399 // If attributes are present, parse them.
400 if (Tok.is(tok::kw___attribute))
401 DeclaratorInfo.AddAttributes(ParseAttributes());
402
403 // '=' assignment-expression
404 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000405 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000406 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000407 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000408 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000409 return ExprError();
410
411 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
412 DeclaratorInfo,EqualLoc,
413 AssignExpr.release()));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000414}
415
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000416/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
417/// This should only be called when the current token is known to be part of
418/// simple-type-specifier.
419///
420/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000421/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000422/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
423/// char
424/// wchar_t
425/// bool
426/// short
427/// int
428/// long
429/// signed
430/// unsigned
431/// float
432/// double
433/// void
434/// [GNU] typeof-specifier
435/// [C++0x] auto [TODO]
436///
437/// type-name:
438/// class-name
439/// enum-name
440/// typedef-name
441///
442void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000443 // Annotate typenames and C++ scope specifiers.
444 TryAnnotateTypeOrScopeToken();
445
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000446 DS.SetRangeStart(Tok.getLocation());
447 const char *PrevSpec;
448 SourceLocation Loc = Tok.getLocation();
449
450 switch (Tok.getKind()) {
451 default:
452 assert(0 && "Not a simple-type-specifier token!");
453 abort();
454
455 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000456 case tok::annot_qualtypename: {
457 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
458 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000459 break;
460 }
461
462 // builtin types
463 case tok::kw_short:
464 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
465 break;
466 case tok::kw_long:
467 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
468 break;
469 case tok::kw_signed:
470 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
471 break;
472 case tok::kw_unsigned:
473 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
474 break;
475 case tok::kw_void:
476 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
477 break;
478 case tok::kw_char:
479 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
480 break;
481 case tok::kw_int:
482 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
483 break;
484 case tok::kw_float:
485 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
486 break;
487 case tok::kw_double:
488 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
489 break;
490 case tok::kw_wchar_t:
491 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
492 break;
493 case tok::kw_bool:
494 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
495 break;
496
497 // GNU typeof support.
498 case tok::kw_typeof:
499 ParseTypeofSpecifier(DS);
500 DS.Finish(Diags, PP.getSourceManager(), getLang());
501 return;
502 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000503 if (Tok.is(tok::annot_qualtypename))
504 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
505 else
506 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000507 ConsumeToken();
508 DS.Finish(Diags, PP.getSourceManager(), getLang());
509}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000510
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000511/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
512/// [dcl.name]), which is a non-empty sequence of type-specifiers,
513/// e.g., "const short int". Note that the DeclSpec is *not* finished
514/// by parsing the type-specifier-seq, because these sequences are
515/// typically followed by some form of declarator. Returns true and
516/// emits diagnostics if this is not a type-specifier-seq, false
517/// otherwise.
518///
519/// type-specifier-seq: [C++ 8.1]
520/// type-specifier type-specifier-seq[opt]
521///
522bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
523 DS.SetRangeStart(Tok.getLocation());
524 const char *PrevSpec = 0;
525 int isInvalid = 0;
526
527 // Parse one or more of the type specifiers.
528 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000529 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000530 return true;
531 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000532 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000533
534 return false;
535}
536
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000537/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000538/// operator name (C++ [over.oper]). If successful, returns the
539/// predefined identifier that corresponds to that overloaded
540/// operator. Otherwise, returns NULL and does not consume any tokens.
541///
542/// operator-function-id: [C++ 13.5]
543/// 'operator' operator
544///
545/// operator: one of
546/// new delete new[] delete[]
547/// + - * / % ^ & | ~
548/// ! = < > += -= *= /= %=
549/// ^= &= |= << >> >>= <<= == !=
550/// <= >= && || ++ -- , ->* ->
551/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000552OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000553 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000554
555 OverloadedOperatorKind Op = OO_None;
556 switch (NextToken().getKind()) {
557 case tok::kw_new:
558 ConsumeToken(); // 'operator'
559 ConsumeToken(); // 'new'
560 if (Tok.is(tok::l_square)) {
561 ConsumeBracket(); // '['
562 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
563 Op = OO_Array_New;
564 } else {
565 Op = OO_New;
566 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000567 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000568
569 case tok::kw_delete:
570 ConsumeToken(); // 'operator'
571 ConsumeToken(); // 'delete'
572 if (Tok.is(tok::l_square)) {
573 ConsumeBracket(); // '['
574 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
575 Op = OO_Array_Delete;
576 } else {
577 Op = OO_Delete;
578 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000579 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000580
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000581#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000582 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000583#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000584#include "clang/Basic/OperatorKinds.def"
585
586 case tok::l_paren:
587 ConsumeToken(); // 'operator'
588 ConsumeParen(); // '('
589 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000590 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000591
592 case tok::l_square:
593 ConsumeToken(); // 'operator'
594 ConsumeBracket(); // '['
595 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000596 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000597
598 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000599 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000600 }
601
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000602 ConsumeToken(); // 'operator'
603 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000604 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000605}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000606
607/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
608/// which expresses the name of a user-defined conversion operator
609/// (C++ [class.conv.fct]p1). Returns the type that this operator is
610/// specifying a conversion for, or NULL if there was an error.
611///
612/// conversion-function-id: [C++ 12.3.2]
613/// operator conversion-type-id
614///
615/// conversion-type-id:
616/// type-specifier-seq conversion-declarator[opt]
617///
618/// conversion-declarator:
619/// ptr-operator conversion-declarator[opt]
620Parser::TypeTy *Parser::ParseConversionFunctionId() {
621 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
622 ConsumeToken(); // 'operator'
623
624 // Parse the type-specifier-seq.
625 DeclSpec DS;
626 if (ParseCXXTypeSpecifierSeq(DS))
627 return 0;
628
629 // Parse the conversion-declarator, which is merely a sequence of
630 // ptr-operators.
631 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000632 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000633
634 // Finish up the type.
635 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
636 if (Result.isInvalid)
637 return 0;
638 else
639 return Result.Val;
640}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000641
642/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
643/// memory in a typesafe manner and call constructors.
644///
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///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000665Parser::OwningExprResult Parser::ParseCXXNewExpression()
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000666{
667 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_new)) &&
668 "Expected :: or 'new' keyword");
669
670 SourceLocation Start = Tok.getLocation();
671 bool UseGlobal = false;
672 if (Tok.is(tok::coloncolon)) {
673 UseGlobal = true;
674 ConsumeToken();
675 }
676
677 assert(Tok.is(tok::kw_new) && "Lookahead should have ensured 'new'");
678 // Consume 'new'
679 ConsumeToken();
680
681 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
682 // second form of new-expression. It can't be a new-type-id.
683
Sebastian Redla55e52c2008-11-25 22:21:31 +0000684 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000685 SourceLocation PlacementLParen, PlacementRParen;
686
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000687 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000688 DeclSpec DS;
689 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000690 if (Tok.is(tok::l_paren)) {
691 // If it turns out to be a placement, we change the type location.
692 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000693 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
694 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000695 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000696 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000697
698 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000699 if (PlacementRParen.isInvalid()) {
700 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000701 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000702 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000703
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000704 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000705 // Reset the placement locations. There was no placement.
706 PlacementLParen = PlacementRParen = SourceLocation();
707 ParenTypeId = true;
708 } else {
709 // We still need the type.
710 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000711 SourceLocation LParen = ConsumeParen();
712 ParseSpecifierQualifierList(DS);
713 ParseDeclarator(DeclaratorInfo);
714 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000715 ParenTypeId = true;
716 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000717 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 Redl4c5d3202008-11-21 19:14:01 +0000724 }
725 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000726 // A new-type-id is a simplified type-id, where essentially the
727 // direct-declarator is replaced by a direct-new-declarator.
728 if (ParseCXXTypeSpecifierSeq(DS))
729 DeclaratorInfo.setInvalidType(true);
730 else
731 ParseDeclaratorInternal(DeclaratorInfo,
732 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000733 ParenTypeId = false;
734 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000735 if (DeclaratorInfo.getInvalidType()) {
736 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000737 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000738 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000739
Sebastian Redla55e52c2008-11-25 22:21:31 +0000740 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000741 SourceLocation ConstructorLParen, ConstructorRParen;
742
743 if (Tok.is(tok::l_paren)) {
744 ConstructorLParen = ConsumeParen();
745 if (Tok.isNot(tok::r_paren)) {
746 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000747 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
748 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000749 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000750 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000751 }
752 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000753 if (ConstructorRParen.isInvalid()) {
754 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000755 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000756 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000757 }
758
Sebastian Redl20df9b72008-12-11 22:51:44 +0000759 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
760 PlacementArgs.take(), PlacementArgs.size(),
761 PlacementRParen, ParenTypeId, DeclaratorInfo,
762 ConstructorLParen, ConstructorArgs.take(),
763 ConstructorArgs.size(), ConstructorRParen));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000764}
765
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000766/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
767/// passed to ParseDeclaratorInternal.
768///
769/// direct-new-declarator:
770/// '[' expression ']'
771/// direct-new-declarator '[' constant-expression ']'
772///
773void Parser::ParseDirectNewDeclarator(Declarator &D)
774{
775 // Parse the array dimensions.
776 bool first = true;
777 while (Tok.is(tok::l_square)) {
778 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000779 OwningExprResult Size(first ? ParseExpression()
780 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000781 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000782 // Recover
783 SkipUntil(tok::r_square);
784 return;
785 }
786 first = false;
787
788 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000789 Size.release(), LLoc));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000790
791 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
792 return;
793 }
794}
795
796/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
797/// This ambiguity appears in the syntax of the C++ new operator.
798///
799/// new-expression:
800/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
801/// new-initializer[opt]
802///
803/// new-placement:
804/// '(' expression-list ')'
805///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000806bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
807 Declarator &D)
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000808{
809 // The '(' was already consumed.
810 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000811 ParseSpecifierQualifierList(D.getMutableDeclSpec());
812 ParseDeclarator(D);
813 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000814 }
815
816 // It's not a type, it has to be an expression list.
817 // Discard the comma locations - ActOnCXXNew has enough parameters.
818 CommaLocsTy CommaLocs;
819 return ParseExpressionList(PlacementArgs, CommaLocs);
820}
821
822/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
823/// to free memory allocated by new.
824///
825/// delete-expression:
826/// '::'[opt] 'delete' cast-expression
827/// '::'[opt] 'delete' '[' ']' cast-expression
Sebastian Redl20df9b72008-12-11 22:51:44 +0000828Parser::OwningExprResult Parser::ParseCXXDeleteExpression()
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000829{
830 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_delete)) &&
831 "Expected :: or 'delete' keyword");
832
833 SourceLocation Start = Tok.getLocation();
834 bool UseGlobal = false;
835 if (Tok.is(tok::coloncolon)) {
836 UseGlobal = true;
837 ConsumeToken();
838 }
839
840 assert(Tok.is(tok::kw_delete) && "Lookahead should have ensured 'delete'");
841 // Consume 'delete'
842 ConsumeToken();
843
844 // Array delete?
845 bool ArrayDelete = false;
846 if (Tok.is(tok::l_square)) {
847 ArrayDelete = true;
848 SourceLocation LHS = ConsumeBracket();
849 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
850 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000851 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000852 }
853
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000854 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000855 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000856 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000857
Sebastian Redl20df9b72008-12-11 22:51:44 +0000858 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
859 Operand.release()));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000860}