blob: b4b6fb533024ea67318ff44a070c441c0eacb154 [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 Kyrtzidiseb83ecd2008-11-08 16:45:02 +000020/// ParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
21///
22/// '::'[opt] nested-name-specifier
23/// '::'
24///
25/// nested-name-specifier:
26/// type-name '::'
27/// namespace-name '::'
28/// nested-name-specifier identifier '::'
29/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
30///
31void Parser::ParseCXXScopeSpecifier(CXXScopeSpec &SS) {
32 assert(isTokenCXXScopeSpecifier() && "Not scope specifier!");
33
34 if (Tok.is(tok::annot_cxxscope)) {
35 SS.setScopeRep(Tok.getAnnotationValue());
36 SS.setRange(Tok.getAnnotationRange());
37 ConsumeToken();
38 return;
39 }
40
41 SS.setBeginLoc(Tok.getLocation());
42
43 // '::'
44
45 if (Tok.is(tok::coloncolon)) {
46 // Global scope.
47 SourceLocation CCLoc = ConsumeToken();
48 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
49 SS.setEndLoc(CCLoc);
50 }
51
52 // nested-name-specifier:
53 // type-name '::'
54 // namespace-name '::'
55 // nested-name-specifier identifier '::'
56 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
57
58 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
59 IdentifierInfo *II = Tok.getIdentifierInfo();
60 SourceLocation IdLoc = ConsumeToken();
61 assert(Tok.is(tok::coloncolon) &&
62 "NextToken() not working properly!");
63 SourceLocation CCLoc = ConsumeToken();
64 if (SS.isInvalid())
65 continue;
66
67 SS.setScopeRep(
68 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II) );
69 SS.setEndLoc(CCLoc);
70 }
71}
72
73/// ParseCXXIdExpression - Handle id-expression.
74///
75/// id-expression:
76/// unqualified-id
77/// qualified-id
78///
79/// unqualified-id:
80/// identifier
81/// operator-function-id
82/// conversion-function-id [TODO]
83/// '~' class-name [TODO]
84/// template-id [TODO]
85///
86/// qualified-id:
87/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
88/// '::' identifier
89/// '::' operator-function-id
90/// '::' template-id [TODO]
91///
92/// nested-name-specifier:
93/// type-name '::'
94/// namespace-name '::'
95/// nested-name-specifier identifier '::'
96/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
97///
98/// NOTE: The standard specifies that, for qualified-id, the parser does not
99/// expect:
100///
101/// '::' conversion-function-id
102/// '::' '~' class-name
103///
104/// This may cause a slight inconsistency on diagnostics:
105///
106/// class C {};
107/// namespace A {}
108/// void f() {
109/// :: A :: ~ C(); // Some Sema error about using destructor with a
110/// // namespace.
111/// :: ~ C(); // Some Parser error like 'unexpected ~'.
112/// }
113///
114/// We simplify the parser a bit and make it work like:
115///
116/// qualified-id:
117/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
118/// '::' unqualified-id
119///
120/// That way Sema can handle and report similar errors for namespaces and the
121/// global scope.
122///
123Parser::ExprResult Parser::ParseCXXIdExpression() {
124 // qualified-id:
125 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
126 // '::' unqualified-id
127 //
128 CXXScopeSpec SS;
129 if (isTokenCXXScopeSpecifier())
130 ParseCXXScopeSpecifier(SS);
131
132 // unqualified-id:
133 // identifier
134 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000135 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000136 // '~' class-name [TODO]
137 // template-id [TODO]
138 //
139 switch (Tok.getKind()) {
140 default:
141 return Diag(Tok, diag::err_expected_unqualified_id);
142
143 case tok::identifier: {
144 // Consume the identifier so that we can see if it is followed by a '('.
145 IdentifierInfo &II = *Tok.getIdentifierInfo();
146 SourceLocation L = ConsumeToken();
147 return Actions.ActOnIdentifierExpr(CurScope, L, II,
148 Tok.is(tok::l_paren), &SS);
149 }
150
151 case tok::kw_operator: {
152 SourceLocation OperatorLoc = Tok.getLocation();
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000153 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
Douglas Gregor487a75a2008-11-19 19:09:45 +0000154 return Actions.ActOnCXXOperatorFunctionIdExpr(CurScope, OperatorLoc, Op,
155 Tok.is(tok::l_paren), SS);
Douglas Gregor2def4832008-11-17 20:34:05 +0000156 } else if (TypeTy *Type = ParseConversionFunctionId()) {
Douglas Gregor487a75a2008-11-19 19:09:45 +0000157 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc,
158 Type, Tok.is(tok::l_paren),
159 SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000160 }
Douglas Gregor2def4832008-11-17 20:34:05 +0000161
162 // We already complained about a bad conversion-function-id,
163 // above.
164 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000165 }
166
167 } // switch.
168
169 assert(0 && "The switch was supposed to take care everything.");
170}
171
Reid Spencer5f016e22007-07-11 17:01:13 +0000172/// ParseCXXCasts - This handles the various ways to cast expressions to another
173/// type.
174///
175/// postfix-expression: [C++ 5.2p1]
176/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
177/// 'static_cast' '<' type-name '>' '(' expression ')'
178/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
179/// 'const_cast' '<' type-name '>' '(' expression ')'
180///
181Parser::ExprResult Parser::ParseCXXCasts() {
182 tok::TokenKind Kind = Tok.getKind();
183 const char *CastName = 0; // For error messages
184
185 switch (Kind) {
186 default: assert(0 && "Unknown C++ cast!"); abort();
187 case tok::kw_const_cast: CastName = "const_cast"; break;
188 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
189 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
190 case tok::kw_static_cast: CastName = "static_cast"; break;
191 }
192
193 SourceLocation OpLoc = ConsumeToken();
194 SourceLocation LAngleBracketLoc = Tok.getLocation();
195
196 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
197 return ExprResult(true);
198
199 TypeTy *CastTy = ParseTypeName();
200 SourceLocation RAngleBracketLoc = Tok.getLocation();
201
Chris Lattner1ab3b962008-11-18 07:48:38 +0000202 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Chris Lattner28eb7e92008-11-23 23:17:07 +0000203 return Diag(LAngleBracketLoc, diag::note_matching) << "<";
Reid Spencer5f016e22007-07-11 17:01:13 +0000204
205 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
206
Chris Lattner1ab3b962008-11-18 07:48:38 +0000207 if (Tok.isNot(tok::l_paren))
208 return Diag(Tok, diag::err_expected_lparen_after) << CastName;
Reid Spencer5f016e22007-07-11 17:01:13 +0000209
210 ExprResult Result = ParseSimpleParenExpression(RParenLoc);
211
212 if (!Result.isInvalid)
Douglas Gregor49badde2008-10-27 19:41:14 +0000213 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
214 LAngleBracketLoc, CastTy, RAngleBracketLoc,
215 LParenLoc, Result.Val, RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000216
217 return Result;
218}
219
Sebastian Redlc42e1182008-11-11 11:37:55 +0000220/// ParseCXXTypeid - This handles the C++ typeid expression.
221///
222/// postfix-expression: [C++ 5.2p1]
223/// 'typeid' '(' expression ')'
224/// 'typeid' '(' type-id ')'
225///
226Parser::ExprResult Parser::ParseCXXTypeid() {
227 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
228
229 SourceLocation OpLoc = ConsumeToken();
230 SourceLocation LParenLoc = Tok.getLocation();
231 SourceLocation RParenLoc;
232
233 // typeid expressions are always parenthesized.
234 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
235 "typeid"))
236 return ExprResult(true);
237
238 Parser::ExprResult Result;
239
240 if (isTypeIdInParens()) {
241 TypeTy *Ty = ParseTypeName();
242
243 // Match the ')'.
244 MatchRHSPunctuation(tok::r_paren, LParenLoc);
245
246 if (!Ty)
247 return ExprResult(true);
248
249 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
250 Ty, RParenLoc);
251 } else {
252 Result = ParseExpression();
253
254 // Match the ')'.
255 if (Result.isInvalid)
256 SkipUntil(tok::r_paren);
257 else {
258 MatchRHSPunctuation(tok::r_paren, LParenLoc);
259
260 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
261 Result.Val, RParenLoc);
262 }
263 }
264
265 return Result;
266}
267
Reid Spencer5f016e22007-07-11 17:01:13 +0000268/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
269///
270/// boolean-literal: [C++ 2.13.5]
271/// 'true'
272/// 'false'
273Parser::ExprResult Parser::ParseCXXBoolLiteral() {
274 tok::TokenKind Kind = Tok.getKind();
Steve Naroff1b273c42007-09-16 14:56:35 +0000275 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Reid Spencer5f016e22007-07-11 17:01:13 +0000276}
Chris Lattner50dd2892008-02-26 00:51:44 +0000277
278/// ParseThrowExpression - This handles the C++ throw expression.
279///
280/// throw-expression: [C++ 15]
281/// 'throw' assignment-expression[opt]
282Parser::ExprResult Parser::ParseThrowExpression() {
283 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000284 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Chris Lattner3e3d3102008-04-06 06:03:03 +0000285
Chris Lattner2a2819a2008-04-06 06:02:23 +0000286 // If the current token isn't the start of an assignment-expression,
287 // then the expression is not present. This handles things like:
288 // "C ? throw : (void)42", which is crazy but legal.
289 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
290 case tok::semi:
291 case tok::r_paren:
292 case tok::r_square:
293 case tok::r_brace:
294 case tok::colon:
295 case tok::comma:
Chris Lattner50dd2892008-02-26 00:51:44 +0000296 return Actions.ActOnCXXThrow(ThrowLoc);
297
Chris Lattner2a2819a2008-04-06 06:02:23 +0000298 default:
Chris Lattner3e3d3102008-04-06 06:03:03 +0000299 ExprResult Expr = ParseAssignmentExpression();
Chris Lattner2a2819a2008-04-06 06:02:23 +0000300 if (Expr.isInvalid) return Expr;
301 return Actions.ActOnCXXThrow(ThrowLoc, Expr.Val);
302 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000303}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000304
305/// ParseCXXThis - This handles the C++ 'this' pointer.
306///
307/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
308/// a non-lvalue expression whose value is the address of the object for which
309/// the function is called.
310Parser::ExprResult Parser::ParseCXXThis() {
311 assert(Tok.is(tok::kw_this) && "Not 'this'!");
312 SourceLocation ThisLoc = ConsumeToken();
Argyrios Kyrtzidis289d7732008-08-16 19:34:46 +0000313 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000314}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000315
316/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
317/// Can be interpreted either as function-style casting ("int(x)")
318/// or class type construction ("ClassType(x,y,z)")
319/// or creation of a value-initialized type ("int()").
320///
321/// postfix-expression: [C++ 5.2p1]
322/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
323/// typename-specifier '(' expression-list[opt] ')' [TODO]
324///
325Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
326 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
327 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
328
329 assert(Tok.is(tok::l_paren) && "Expected '('!");
330 SourceLocation LParenLoc = ConsumeParen();
331
Sebastian Redla55e52c2008-11-25 22:21:31 +0000332 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000333 CommaLocsTy CommaLocs;
334
335 if (Tok.isNot(tok::r_paren)) {
336 if (ParseExpressionList(Exprs, CommaLocs)) {
337 SkipUntil(tok::r_paren);
338 return ExprResult(true);
339 }
340 }
341
342 // Match the ')'.
343 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
344
345 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
346 "Unexpected number of commas!");
347 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
348 LParenLoc,
Sebastian Redla55e52c2008-11-25 22:21:31 +0000349 Exprs.take(), Exprs.size(),
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000350 &CommaLocs[0], RParenLoc);
351}
352
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000353/// ParseCXXCondition - if/switch/while/for condition expression.
354///
355/// condition:
356/// expression
357/// type-specifier-seq declarator '=' assignment-expression
358/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
359/// '=' assignment-expression
360///
361Parser::ExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000362 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000363 return ParseExpression(); // expression
364
365 SourceLocation StartLoc = Tok.getLocation();
366
367 // type-specifier-seq
368 DeclSpec DS;
369 ParseSpecifierQualifierList(DS);
370
371 // declarator
372 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
373 ParseDeclarator(DeclaratorInfo);
374
375 // simple-asm-expr[opt]
376 if (Tok.is(tok::kw_asm)) {
377 ExprResult AsmLabel = ParseSimpleAsm();
378 if (AsmLabel.isInvalid) {
379 SkipUntil(tok::semi);
380 return true;
381 }
382 DeclaratorInfo.setAsmLabel(AsmLabel.Val);
383 }
384
385 // If attributes are present, parse them.
386 if (Tok.is(tok::kw___attribute))
387 DeclaratorInfo.AddAttributes(ParseAttributes());
388
389 // '=' assignment-expression
390 if (Tok.isNot(tok::equal))
391 return Diag(Tok, diag::err_expected_equal_after_declarator);
392 SourceLocation EqualLoc = ConsumeToken();
393 ExprResult AssignExpr = ParseAssignmentExpression();
394 if (AssignExpr.isInvalid)
395 return true;
396
397 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
398 DeclaratorInfo,
399 EqualLoc, AssignExpr.Val);
400}
401
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000402/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
403/// This should only be called when the current token is known to be part of
404/// simple-type-specifier.
405///
406/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000407/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000408/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
409/// char
410/// wchar_t
411/// bool
412/// short
413/// int
414/// long
415/// signed
416/// unsigned
417/// float
418/// double
419/// void
420/// [GNU] typeof-specifier
421/// [C++0x] auto [TODO]
422///
423/// type-name:
424/// class-name
425/// enum-name
426/// typedef-name
427///
428void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000429 // Annotate typenames and C++ scope specifiers.
430 TryAnnotateTypeOrScopeToken();
431
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000432 DS.SetRangeStart(Tok.getLocation());
433 const char *PrevSpec;
434 SourceLocation Loc = Tok.getLocation();
435
436 switch (Tok.getKind()) {
437 default:
438 assert(0 && "Not a simple-type-specifier token!");
439 abort();
440
441 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000442 case tok::annot_qualtypename: {
443 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
444 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000445 break;
446 }
447
448 // builtin types
449 case tok::kw_short:
450 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
451 break;
452 case tok::kw_long:
453 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
454 break;
455 case tok::kw_signed:
456 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
457 break;
458 case tok::kw_unsigned:
459 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
460 break;
461 case tok::kw_void:
462 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
463 break;
464 case tok::kw_char:
465 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
466 break;
467 case tok::kw_int:
468 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
469 break;
470 case tok::kw_float:
471 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
472 break;
473 case tok::kw_double:
474 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
475 break;
476 case tok::kw_wchar_t:
477 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
478 break;
479 case tok::kw_bool:
480 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
481 break;
482
483 // GNU typeof support.
484 case tok::kw_typeof:
485 ParseTypeofSpecifier(DS);
486 DS.Finish(Diags, PP.getSourceManager(), getLang());
487 return;
488 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000489 if (Tok.is(tok::annot_qualtypename))
490 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
491 else
492 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000493 ConsumeToken();
494 DS.Finish(Diags, PP.getSourceManager(), getLang());
495}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000496
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000497/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
498/// [dcl.name]), which is a non-empty sequence of type-specifiers,
499/// e.g., "const short int". Note that the DeclSpec is *not* finished
500/// by parsing the type-specifier-seq, because these sequences are
501/// typically followed by some form of declarator. Returns true and
502/// emits diagnostics if this is not a type-specifier-seq, false
503/// otherwise.
504///
505/// type-specifier-seq: [C++ 8.1]
506/// type-specifier type-specifier-seq[opt]
507///
508bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
509 DS.SetRangeStart(Tok.getLocation());
510 const char *PrevSpec = 0;
511 int isInvalid = 0;
512
513 // Parse one or more of the type specifiers.
514 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000515 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000516 return true;
517 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000518 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000519
520 return false;
521}
522
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000523/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000524/// operator name (C++ [over.oper]). If successful, returns the
525/// predefined identifier that corresponds to that overloaded
526/// operator. Otherwise, returns NULL and does not consume any tokens.
527///
528/// operator-function-id: [C++ 13.5]
529/// 'operator' operator
530///
531/// operator: one of
532/// new delete new[] delete[]
533/// + - * / % ^ & | ~
534/// ! = < > += -= *= /= %=
535/// ^= &= |= << >> >>= <<= == !=
536/// <= >= && || ++ -- , ->* ->
537/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000538OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000539 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000540
541 OverloadedOperatorKind Op = OO_None;
542 switch (NextToken().getKind()) {
543 case tok::kw_new:
544 ConsumeToken(); // 'operator'
545 ConsumeToken(); // 'new'
546 if (Tok.is(tok::l_square)) {
547 ConsumeBracket(); // '['
548 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
549 Op = OO_Array_New;
550 } else {
551 Op = OO_New;
552 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000553 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000554
555 case tok::kw_delete:
556 ConsumeToken(); // 'operator'
557 ConsumeToken(); // 'delete'
558 if (Tok.is(tok::l_square)) {
559 ConsumeBracket(); // '['
560 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
561 Op = OO_Array_Delete;
562 } else {
563 Op = OO_Delete;
564 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000565 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000566
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000567#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000568 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000569#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000570#include "clang/Basic/OperatorKinds.def"
571
572 case tok::l_paren:
573 ConsumeToken(); // 'operator'
574 ConsumeParen(); // '('
575 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000576 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000577
578 case tok::l_square:
579 ConsumeToken(); // 'operator'
580 ConsumeBracket(); // '['
581 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000582 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000583
584 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000585 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000586 }
587
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000588 ConsumeToken(); // 'operator'
589 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000590 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000591}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000592
593/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
594/// which expresses the name of a user-defined conversion operator
595/// (C++ [class.conv.fct]p1). Returns the type that this operator is
596/// specifying a conversion for, or NULL if there was an error.
597///
598/// conversion-function-id: [C++ 12.3.2]
599/// operator conversion-type-id
600///
601/// conversion-type-id:
602/// type-specifier-seq conversion-declarator[opt]
603///
604/// conversion-declarator:
605/// ptr-operator conversion-declarator[opt]
606Parser::TypeTy *Parser::ParseConversionFunctionId() {
607 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
608 ConsumeToken(); // 'operator'
609
610 // Parse the type-specifier-seq.
611 DeclSpec DS;
612 if (ParseCXXTypeSpecifierSeq(DS))
613 return 0;
614
615 // Parse the conversion-declarator, which is merely a sequence of
616 // ptr-operators.
617 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000618 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000619
620 // Finish up the type.
621 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
622 if (Result.isInvalid)
623 return 0;
624 else
625 return Result.Val;
626}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000627
628/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
629/// memory in a typesafe manner and call constructors.
630///
631/// new-expression:
632/// '::'[opt] 'new' new-placement[opt] new-type-id
633/// new-initializer[opt]
634/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
635/// new-initializer[opt]
636///
637/// new-placement:
638/// '(' expression-list ')'
639///
640/// new-initializer:
641/// '(' expression-list[opt] ')'
642/// [C++0x] braced-init-list [TODO]
643///
644Parser::ExprResult Parser::ParseCXXNewExpression()
645{
646 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_new)) &&
647 "Expected :: or 'new' keyword");
648
649 SourceLocation Start = Tok.getLocation();
650 bool UseGlobal = false;
651 if (Tok.is(tok::coloncolon)) {
652 UseGlobal = true;
653 ConsumeToken();
654 }
655
656 assert(Tok.is(tok::kw_new) && "Lookahead should have ensured 'new'");
657 // Consume 'new'
658 ConsumeToken();
659
660 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
661 // second form of new-expression. It can't be a new-type-id.
662
Sebastian Redla55e52c2008-11-25 22:21:31 +0000663 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000664 SourceLocation PlacementLParen, PlacementRParen;
665
666 TypeTy *Ty = 0;
667 SourceLocation TyStart, TyEnd;
668 bool ParenTypeId;
669 if (Tok.is(tok::l_paren)) {
670 // If it turns out to be a placement, we change the type location.
671 PlacementLParen = ConsumeParen();
672 TyStart = Tok.getLocation();
673 if (ParseExpressionListOrTypeId(PlacementArgs, Ty))
674 return true;
675 TyEnd = Tok.getLocation();
676
677 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
678 if (PlacementRParen.isInvalid())
679 return true;
680
681 if (Ty) {
682 // Reset the placement locations. There was no placement.
683 PlacementLParen = PlacementRParen = SourceLocation();
684 ParenTypeId = true;
685 } else {
686 // We still need the type.
687 if (Tok.is(tok::l_paren)) {
688 ConsumeParen();
689 TyStart = Tok.getLocation();
690 Ty = ParseTypeName(/*CXXNewMode=*/true);
691 ParenTypeId = true;
692 } else {
693 TyStart = Tok.getLocation();
694 Ty = ParseNewTypeId();
695 ParenTypeId = false;
696 }
697 if (!Ty)
698 return true;
699 TyEnd = Tok.getLocation();
700 }
701 } else {
702 TyStart = Tok.getLocation();
703 Ty = ParseNewTypeId();
704 if (!Ty)
705 return true;
706 TyEnd = Tok.getLocation();
707 ParenTypeId = false;
708 }
709
Sebastian Redla55e52c2008-11-25 22:21:31 +0000710 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000711 SourceLocation ConstructorLParen, ConstructorRParen;
712
713 if (Tok.is(tok::l_paren)) {
714 ConstructorLParen = ConsumeParen();
715 if (Tok.isNot(tok::r_paren)) {
716 CommaLocsTy CommaLocs;
717 if (ParseExpressionList(ConstructorArgs, CommaLocs))
718 return true;
719 }
720 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
721 if (ConstructorRParen.isInvalid())
722 return true;
723 }
724
725 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
Sebastian Redla55e52c2008-11-25 22:21:31 +0000726 PlacementArgs.take(), PlacementArgs.size(),
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000727 PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
Sebastian Redla55e52c2008-11-25 22:21:31 +0000728 ConstructorLParen, ConstructorArgs.take(),
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000729 ConstructorArgs.size(), ConstructorRParen);
730}
731
732/// ParseNewTypeId - Parses a type ID as it appears in a new expression.
733/// The most interesting part of this is the new-declarator, which can be a
734/// multi-dimensional array, of which the first has a non-constant expression as
735/// the size, e.g.
736/// @code new int[runtimeSize()][2][2] @endcode
737///
738/// new-type-id:
739/// type-specifier-seq new-declarator[opt]
740///
741/// new-declarator:
742/// ptr-operator new-declarator[opt]
743/// direct-new-declarator
744///
745Parser::TypeTy * Parser::ParseNewTypeId()
746{
747 DeclSpec DS;
748 if (ParseCXXTypeSpecifierSeq(DS))
749 return 0;
750
751 // A new-declarator is a simplified version of a declarator. We use
752 // ParseDeclaratorInternal, but pass our own direct declarator parser,
753 // one that parses a direct-new-declarator.
754 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
755 ParseDeclaratorInternal(DeclaratorInfo, &Parser::ParseDirectNewDeclarator);
756
757 TypeTy *Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo,
758 /*CXXNewMode=*/true).Val;
759 return DeclaratorInfo.getInvalidType() ? 0 : Ty;
760}
761
762/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
763/// passed to ParseDeclaratorInternal.
764///
765/// direct-new-declarator:
766/// '[' expression ']'
767/// direct-new-declarator '[' constant-expression ']'
768///
769void Parser::ParseDirectNewDeclarator(Declarator &D)
770{
771 // Parse the array dimensions.
772 bool first = true;
773 while (Tok.is(tok::l_square)) {
774 SourceLocation LLoc = ConsumeBracket();
775 ExprResult Size = first ? ParseExpression() : ParseConstantExpression();
776 if (Size.isInvalid) {
777 // Recover
778 SkipUntil(tok::r_square);
779 return;
780 }
781 first = false;
782
783 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
784 Size.Val, LLoc));
785
786 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
787 return;
788 }
789}
790
791/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
792/// This ambiguity appears in the syntax of the C++ new operator.
793///
794/// new-expression:
795/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
796/// new-initializer[opt]
797///
798/// new-placement:
799/// '(' expression-list ')'
800///
801bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, TypeTy *&Ty)
802{
803 // The '(' was already consumed.
804 if (isTypeIdInParens()) {
805 Ty = ParseTypeName(/*CXXNewMode=*/true);
806 return Ty == 0;
807 }
808
809 // It's not a type, it has to be an expression list.
810 // Discard the comma locations - ActOnCXXNew has enough parameters.
811 CommaLocsTy CommaLocs;
812 return ParseExpressionList(PlacementArgs, CommaLocs);
813}
814
815/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
816/// to free memory allocated by new.
817///
818/// delete-expression:
819/// '::'[opt] 'delete' cast-expression
820/// '::'[opt] 'delete' '[' ']' cast-expression
821Parser::ExprResult Parser::ParseCXXDeleteExpression()
822{
823 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_delete)) &&
824 "Expected :: or 'delete' keyword");
825
826 SourceLocation Start = Tok.getLocation();
827 bool UseGlobal = false;
828 if (Tok.is(tok::coloncolon)) {
829 UseGlobal = true;
830 ConsumeToken();
831 }
832
833 assert(Tok.is(tok::kw_delete) && "Lookahead should have ensured 'delete'");
834 // Consume 'delete'
835 ConsumeToken();
836
837 // Array delete?
838 bool ArrayDelete = false;
839 if (Tok.is(tok::l_square)) {
840 ArrayDelete = true;
841 SourceLocation LHS = ConsumeBracket();
842 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
843 if (RHS.isInvalid())
844 return true;
845 }
846
847 ExprResult Operand = ParseCastExpression(false);
848 if (Operand.isInvalid)
849 return Operand;
850
851 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.Val);
852}