blob: d995b887f26c99b83938ce7f5068c5b9da62a083 [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
41 if (Tok.is(tok::annot_cxxscope)) {
42 SS.setScopeRep(Tok.getAnnotationValue());
43 SS.setRange(Tok.getAnnotationRange());
44 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000045 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000046 }
47
48 SS.setBeginLoc(Tok.getLocation());
49
50 // '::'
51
52 if (Tok.is(tok::coloncolon)) {
53 // Global scope.
54 SourceLocation CCLoc = ConsumeToken();
55 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
56 SS.setEndLoc(CCLoc);
57 }
58
59 // nested-name-specifier:
60 // type-name '::'
61 // namespace-name '::'
62 // nested-name-specifier identifier '::'
63 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
64
65 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
66 IdentifierInfo *II = Tok.getIdentifierInfo();
67 SourceLocation IdLoc = ConsumeToken();
68 assert(Tok.is(tok::coloncolon) &&
69 "NextToken() not working properly!");
70 SourceLocation CCLoc = ConsumeToken();
71 if (SS.isInvalid())
72 continue;
73
74 SS.setScopeRep(
75 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II) );
76 SS.setEndLoc(CCLoc);
77 }
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000078
79 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000080}
81
82/// ParseCXXIdExpression - Handle id-expression.
83///
84/// id-expression:
85/// unqualified-id
86/// qualified-id
87///
88/// unqualified-id:
89/// identifier
90/// operator-function-id
91/// conversion-function-id [TODO]
92/// '~' class-name [TODO]
93/// template-id [TODO]
94///
95/// qualified-id:
96/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
97/// '::' identifier
98/// '::' operator-function-id
99/// '::' template-id [TODO]
100///
101/// nested-name-specifier:
102/// type-name '::'
103/// namespace-name '::'
104/// nested-name-specifier identifier '::'
105/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
106///
107/// NOTE: The standard specifies that, for qualified-id, the parser does not
108/// expect:
109///
110/// '::' conversion-function-id
111/// '::' '~' class-name
112///
113/// This may cause a slight inconsistency on diagnostics:
114///
115/// class C {};
116/// namespace A {}
117/// void f() {
118/// :: A :: ~ C(); // Some Sema error about using destructor with a
119/// // namespace.
120/// :: ~ C(); // Some Parser error like 'unexpected ~'.
121/// }
122///
123/// We simplify the parser a bit and make it work like:
124///
125/// qualified-id:
126/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
127/// '::' unqualified-id
128///
129/// That way Sema can handle and report similar errors for namespaces and the
130/// global scope.
131///
132Parser::ExprResult Parser::ParseCXXIdExpression() {
133 // qualified-id:
134 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
135 // '::' unqualified-id
136 //
137 CXXScopeSpec SS;
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000138 MaybeParseCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000139
140 // unqualified-id:
141 // identifier
142 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000143 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000144 // '~' class-name [TODO]
145 // template-id [TODO]
146 //
147 switch (Tok.getKind()) {
148 default:
149 return Diag(Tok, diag::err_expected_unqualified_id);
150
151 case tok::identifier: {
152 // Consume the identifier so that we can see if it is followed by a '('.
153 IdentifierInfo &II = *Tok.getIdentifierInfo();
154 SourceLocation L = ConsumeToken();
155 return Actions.ActOnIdentifierExpr(CurScope, L, II,
156 Tok.is(tok::l_paren), &SS);
157 }
158
159 case tok::kw_operator: {
160 SourceLocation OperatorLoc = Tok.getLocation();
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000161 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
Douglas Gregor487a75a2008-11-19 19:09:45 +0000162 return Actions.ActOnCXXOperatorFunctionIdExpr(CurScope, OperatorLoc, Op,
163 Tok.is(tok::l_paren), SS);
Douglas Gregor2def4832008-11-17 20:34:05 +0000164 } else if (TypeTy *Type = ParseConversionFunctionId()) {
Douglas Gregor487a75a2008-11-19 19:09:45 +0000165 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc,
166 Type, Tok.is(tok::l_paren),
167 SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000168 }
Douglas Gregor2def4832008-11-17 20:34:05 +0000169
170 // We already complained about a bad conversion-function-id,
171 // above.
172 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000173 }
174
175 } // switch.
176
177 assert(0 && "The switch was supposed to take care everything.");
178}
179
Reid Spencer5f016e22007-07-11 17:01:13 +0000180/// ParseCXXCasts - This handles the various ways to cast expressions to another
181/// type.
182///
183/// postfix-expression: [C++ 5.2p1]
184/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
185/// 'static_cast' '<' type-name '>' '(' expression ')'
186/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
187/// 'const_cast' '<' type-name '>' '(' expression ')'
188///
189Parser::ExprResult Parser::ParseCXXCasts() {
190 tok::TokenKind Kind = Tok.getKind();
191 const char *CastName = 0; // For error messages
192
193 switch (Kind) {
194 default: assert(0 && "Unknown C++ cast!"); abort();
195 case tok::kw_const_cast: CastName = "const_cast"; break;
196 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
197 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
198 case tok::kw_static_cast: CastName = "static_cast"; break;
199 }
200
201 SourceLocation OpLoc = ConsumeToken();
202 SourceLocation LAngleBracketLoc = Tok.getLocation();
203
204 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
205 return ExprResult(true);
206
207 TypeTy *CastTy = ParseTypeName();
208 SourceLocation RAngleBracketLoc = Tok.getLocation();
209
Chris Lattner1ab3b962008-11-18 07:48:38 +0000210 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Chris Lattner28eb7e92008-11-23 23:17:07 +0000211 return Diag(LAngleBracketLoc, diag::note_matching) << "<";
Reid Spencer5f016e22007-07-11 17:01:13 +0000212
213 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
214
Chris Lattner1ab3b962008-11-18 07:48:38 +0000215 if (Tok.isNot(tok::l_paren))
216 return Diag(Tok, diag::err_expected_lparen_after) << CastName;
Reid Spencer5f016e22007-07-11 17:01:13 +0000217
218 ExprResult Result = ParseSimpleParenExpression(RParenLoc);
219
220 if (!Result.isInvalid)
Douglas Gregor49badde2008-10-27 19:41:14 +0000221 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
222 LAngleBracketLoc, CastTy, RAngleBracketLoc,
223 LParenLoc, Result.Val, RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000224
225 return Result;
226}
227
Sebastian Redlc42e1182008-11-11 11:37:55 +0000228/// ParseCXXTypeid - This handles the C++ typeid expression.
229///
230/// postfix-expression: [C++ 5.2p1]
231/// 'typeid' '(' expression ')'
232/// 'typeid' '(' type-id ')'
233///
234Parser::ExprResult Parser::ParseCXXTypeid() {
235 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
236
237 SourceLocation OpLoc = ConsumeToken();
238 SourceLocation LParenLoc = Tok.getLocation();
239 SourceLocation RParenLoc;
240
241 // typeid expressions are always parenthesized.
242 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
243 "typeid"))
244 return ExprResult(true);
245
246 Parser::ExprResult Result;
247
248 if (isTypeIdInParens()) {
249 TypeTy *Ty = ParseTypeName();
250
251 // Match the ')'.
252 MatchRHSPunctuation(tok::r_paren, LParenLoc);
253
254 if (!Ty)
255 return ExprResult(true);
256
257 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
258 Ty, RParenLoc);
259 } else {
260 Result = ParseExpression();
261
262 // Match the ')'.
263 if (Result.isInvalid)
264 SkipUntil(tok::r_paren);
265 else {
266 MatchRHSPunctuation(tok::r_paren, LParenLoc);
267
268 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
269 Result.Val, RParenLoc);
270 }
271 }
272
273 return Result;
274}
275
Reid Spencer5f016e22007-07-11 17:01:13 +0000276/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
277///
278/// boolean-literal: [C++ 2.13.5]
279/// 'true'
280/// 'false'
281Parser::ExprResult Parser::ParseCXXBoolLiteral() {
282 tok::TokenKind Kind = Tok.getKind();
Steve Naroff1b273c42007-09-16 14:56:35 +0000283 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Reid Spencer5f016e22007-07-11 17:01:13 +0000284}
Chris Lattner50dd2892008-02-26 00:51:44 +0000285
286/// ParseThrowExpression - This handles the C++ throw expression.
287///
288/// throw-expression: [C++ 15]
289/// 'throw' assignment-expression[opt]
290Parser::ExprResult Parser::ParseThrowExpression() {
291 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000292 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Chris Lattner3e3d3102008-04-06 06:03:03 +0000293
Chris Lattner2a2819a2008-04-06 06:02:23 +0000294 // If the current token isn't the start of an assignment-expression,
295 // then the expression is not present. This handles things like:
296 // "C ? throw : (void)42", which is crazy but legal.
297 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
298 case tok::semi:
299 case tok::r_paren:
300 case tok::r_square:
301 case tok::r_brace:
302 case tok::colon:
303 case tok::comma:
Chris Lattner50dd2892008-02-26 00:51:44 +0000304 return Actions.ActOnCXXThrow(ThrowLoc);
305
Chris Lattner2a2819a2008-04-06 06:02:23 +0000306 default:
Chris Lattner3e3d3102008-04-06 06:03:03 +0000307 ExprResult Expr = ParseAssignmentExpression();
Chris Lattner2a2819a2008-04-06 06:02:23 +0000308 if (Expr.isInvalid) return Expr;
309 return Actions.ActOnCXXThrow(ThrowLoc, Expr.Val);
310 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000311}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000312
313/// ParseCXXThis - This handles the C++ 'this' pointer.
314///
315/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
316/// a non-lvalue expression whose value is the address of the object for which
317/// the function is called.
318Parser::ExprResult Parser::ParseCXXThis() {
319 assert(Tok.is(tok::kw_this) && "Not 'this'!");
320 SourceLocation ThisLoc = ConsumeToken();
Argyrios Kyrtzidis289d7732008-08-16 19:34:46 +0000321 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000322}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000323
324/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
325/// Can be interpreted either as function-style casting ("int(x)")
326/// or class type construction ("ClassType(x,y,z)")
327/// or creation of a value-initialized type ("int()").
328///
329/// postfix-expression: [C++ 5.2p1]
330/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
331/// typename-specifier '(' expression-list[opt] ')' [TODO]
332///
333Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
334 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
335 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
336
337 assert(Tok.is(tok::l_paren) && "Expected '('!");
338 SourceLocation LParenLoc = ConsumeParen();
339
Sebastian Redla55e52c2008-11-25 22:21:31 +0000340 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000341 CommaLocsTy CommaLocs;
342
343 if (Tok.isNot(tok::r_paren)) {
344 if (ParseExpressionList(Exprs, CommaLocs)) {
345 SkipUntil(tok::r_paren);
346 return ExprResult(true);
347 }
348 }
349
350 // Match the ')'.
351 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
352
353 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
354 "Unexpected number of commas!");
355 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
356 LParenLoc,
Sebastian Redla55e52c2008-11-25 22:21:31 +0000357 Exprs.take(), Exprs.size(),
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000358 &CommaLocs[0], RParenLoc);
359}
360
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000361/// ParseCXXCondition - if/switch/while/for condition expression.
362///
363/// condition:
364/// expression
365/// type-specifier-seq declarator '=' assignment-expression
366/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
367/// '=' assignment-expression
368///
369Parser::ExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000370 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000371 return ParseExpression(); // expression
372
373 SourceLocation StartLoc = Tok.getLocation();
374
375 // type-specifier-seq
376 DeclSpec DS;
377 ParseSpecifierQualifierList(DS);
378
379 // declarator
380 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
381 ParseDeclarator(DeclaratorInfo);
382
383 // simple-asm-expr[opt]
384 if (Tok.is(tok::kw_asm)) {
385 ExprResult AsmLabel = ParseSimpleAsm();
386 if (AsmLabel.isInvalid) {
387 SkipUntil(tok::semi);
388 return true;
389 }
390 DeclaratorInfo.setAsmLabel(AsmLabel.Val);
391 }
392
393 // If attributes are present, parse them.
394 if (Tok.is(tok::kw___attribute))
395 DeclaratorInfo.AddAttributes(ParseAttributes());
396
397 // '=' assignment-expression
398 if (Tok.isNot(tok::equal))
399 return Diag(Tok, diag::err_expected_equal_after_declarator);
400 SourceLocation EqualLoc = ConsumeToken();
401 ExprResult AssignExpr = ParseAssignmentExpression();
402 if (AssignExpr.isInvalid)
403 return true;
404
405 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
406 DeclaratorInfo,
407 EqualLoc, AssignExpr.Val);
408}
409
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000410/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
411/// This should only be called when the current token is known to be part of
412/// simple-type-specifier.
413///
414/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000415/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000416/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
417/// char
418/// wchar_t
419/// bool
420/// short
421/// int
422/// long
423/// signed
424/// unsigned
425/// float
426/// double
427/// void
428/// [GNU] typeof-specifier
429/// [C++0x] auto [TODO]
430///
431/// type-name:
432/// class-name
433/// enum-name
434/// typedef-name
435///
436void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000437 // Annotate typenames and C++ scope specifiers.
438 TryAnnotateTypeOrScopeToken();
439
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000440 DS.SetRangeStart(Tok.getLocation());
441 const char *PrevSpec;
442 SourceLocation Loc = Tok.getLocation();
443
444 switch (Tok.getKind()) {
445 default:
446 assert(0 && "Not a simple-type-specifier token!");
447 abort();
448
449 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000450 case tok::annot_qualtypename: {
451 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
452 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000453 break;
454 }
455
456 // builtin types
457 case tok::kw_short:
458 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
459 break;
460 case tok::kw_long:
461 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
462 break;
463 case tok::kw_signed:
464 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
465 break;
466 case tok::kw_unsigned:
467 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
468 break;
469 case tok::kw_void:
470 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
471 break;
472 case tok::kw_char:
473 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
474 break;
475 case tok::kw_int:
476 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
477 break;
478 case tok::kw_float:
479 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
480 break;
481 case tok::kw_double:
482 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
483 break;
484 case tok::kw_wchar_t:
485 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
486 break;
487 case tok::kw_bool:
488 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
489 break;
490
491 // GNU typeof support.
492 case tok::kw_typeof:
493 ParseTypeofSpecifier(DS);
494 DS.Finish(Diags, PP.getSourceManager(), getLang());
495 return;
496 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000497 if (Tok.is(tok::annot_qualtypename))
498 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
499 else
500 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000501 ConsumeToken();
502 DS.Finish(Diags, PP.getSourceManager(), getLang());
503}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000504
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000505/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
506/// [dcl.name]), which is a non-empty sequence of type-specifiers,
507/// e.g., "const short int". Note that the DeclSpec is *not* finished
508/// by parsing the type-specifier-seq, because these sequences are
509/// typically followed by some form of declarator. Returns true and
510/// emits diagnostics if this is not a type-specifier-seq, false
511/// otherwise.
512///
513/// type-specifier-seq: [C++ 8.1]
514/// type-specifier type-specifier-seq[opt]
515///
516bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
517 DS.SetRangeStart(Tok.getLocation());
518 const char *PrevSpec = 0;
519 int isInvalid = 0;
520
521 // Parse one or more of the type specifiers.
522 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000523 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000524 return true;
525 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000526 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000527
528 return false;
529}
530
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000531/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000532/// operator name (C++ [over.oper]). If successful, returns the
533/// predefined identifier that corresponds to that overloaded
534/// operator. Otherwise, returns NULL and does not consume any tokens.
535///
536/// operator-function-id: [C++ 13.5]
537/// 'operator' operator
538///
539/// operator: one of
540/// new delete new[] delete[]
541/// + - * / % ^ & | ~
542/// ! = < > += -= *= /= %=
543/// ^= &= |= << >> >>= <<= == !=
544/// <= >= && || ++ -- , ->* ->
545/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000546OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000547 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000548
549 OverloadedOperatorKind Op = OO_None;
550 switch (NextToken().getKind()) {
551 case tok::kw_new:
552 ConsumeToken(); // 'operator'
553 ConsumeToken(); // 'new'
554 if (Tok.is(tok::l_square)) {
555 ConsumeBracket(); // '['
556 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
557 Op = OO_Array_New;
558 } else {
559 Op = OO_New;
560 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000561 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000562
563 case tok::kw_delete:
564 ConsumeToken(); // 'operator'
565 ConsumeToken(); // 'delete'
566 if (Tok.is(tok::l_square)) {
567 ConsumeBracket(); // '['
568 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
569 Op = OO_Array_Delete;
570 } else {
571 Op = OO_Delete;
572 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000573 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000574
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000575#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000576 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000577#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000578#include "clang/Basic/OperatorKinds.def"
579
580 case tok::l_paren:
581 ConsumeToken(); // 'operator'
582 ConsumeParen(); // '('
583 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000584 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000585
586 case tok::l_square:
587 ConsumeToken(); // 'operator'
588 ConsumeBracket(); // '['
589 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000590 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000591
592 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000593 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000594 }
595
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000596 ConsumeToken(); // 'operator'
597 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000598 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000599}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000600
601/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
602/// which expresses the name of a user-defined conversion operator
603/// (C++ [class.conv.fct]p1). Returns the type that this operator is
604/// specifying a conversion for, or NULL if there was an error.
605///
606/// conversion-function-id: [C++ 12.3.2]
607/// operator conversion-type-id
608///
609/// conversion-type-id:
610/// type-specifier-seq conversion-declarator[opt]
611///
612/// conversion-declarator:
613/// ptr-operator conversion-declarator[opt]
614Parser::TypeTy *Parser::ParseConversionFunctionId() {
615 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
616 ConsumeToken(); // 'operator'
617
618 // Parse the type-specifier-seq.
619 DeclSpec DS;
620 if (ParseCXXTypeSpecifierSeq(DS))
621 return 0;
622
623 // Parse the conversion-declarator, which is merely a sequence of
624 // ptr-operators.
625 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000626 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000627
628 // Finish up the type.
629 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
630 if (Result.isInvalid)
631 return 0;
632 else
633 return Result.Val;
634}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000635
636/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
637/// memory in a typesafe manner and call constructors.
638///
639/// new-expression:
640/// '::'[opt] 'new' new-placement[opt] new-type-id
641/// new-initializer[opt]
642/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
643/// new-initializer[opt]
644///
645/// new-placement:
646/// '(' expression-list ')'
647///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000648/// new-type-id:
649/// type-specifier-seq new-declarator[opt]
650///
651/// new-declarator:
652/// ptr-operator new-declarator[opt]
653/// direct-new-declarator
654///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000655/// new-initializer:
656/// '(' expression-list[opt] ')'
657/// [C++0x] braced-init-list [TODO]
658///
659Parser::ExprResult Parser::ParseCXXNewExpression()
660{
661 assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_new)) &&
662 "Expected :: or 'new' keyword");
663
664 SourceLocation Start = Tok.getLocation();
665 bool UseGlobal = false;
666 if (Tok.is(tok::coloncolon)) {
667 UseGlobal = true;
668 ConsumeToken();
669 }
670
671 assert(Tok.is(tok::kw_new) && "Lookahead should have ensured 'new'");
672 // Consume 'new'
673 ConsumeToken();
674
675 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
676 // second form of new-expression. It can't be a new-type-id.
677
Sebastian Redla55e52c2008-11-25 22:21:31 +0000678 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000679 SourceLocation PlacementLParen, PlacementRParen;
680
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000681 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000682 DeclSpec DS;
683 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000684 if (Tok.is(tok::l_paren)) {
685 // If it turns out to be a placement, we change the type location.
686 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000687 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
688 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000689 return true;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000690 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000691
692 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000693 if (PlacementRParen.isInvalid()) {
694 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000695 return true;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000696 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000697
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000698 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000699 // Reset the placement locations. There was no placement.
700 PlacementLParen = PlacementRParen = SourceLocation();
701 ParenTypeId = true;
702 } else {
703 // We still need the type.
704 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000705 SourceLocation LParen = ConsumeParen();
706 ParseSpecifierQualifierList(DS);
707 ParseDeclarator(DeclaratorInfo);
708 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000709 ParenTypeId = true;
710 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000711 if (ParseCXXTypeSpecifierSeq(DS))
712 DeclaratorInfo.setInvalidType(true);
713 else
714 ParseDeclaratorInternal(DeclaratorInfo,
715 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000716 ParenTypeId = false;
717 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000718 }
719 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000720 // A new-type-id is a simplified type-id, where essentially the
721 // direct-declarator is replaced by a direct-new-declarator.
722 if (ParseCXXTypeSpecifierSeq(DS))
723 DeclaratorInfo.setInvalidType(true);
724 else
725 ParseDeclaratorInternal(DeclaratorInfo,
726 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000727 ParenTypeId = false;
728 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000729 if (DeclaratorInfo.getInvalidType()) {
730 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
731 return true;
732 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000733
Sebastian Redla55e52c2008-11-25 22:21:31 +0000734 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000735 SourceLocation ConstructorLParen, ConstructorRParen;
736
737 if (Tok.is(tok::l_paren)) {
738 ConstructorLParen = ConsumeParen();
739 if (Tok.isNot(tok::r_paren)) {
740 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000741 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
742 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000743 return true;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000744 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000745 }
746 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000747 if (ConstructorRParen.isInvalid()) {
748 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000749 return true;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000750 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000751 }
752
753 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
Sebastian Redla55e52c2008-11-25 22:21:31 +0000754 PlacementArgs.take(), PlacementArgs.size(),
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000755 PlacementRParen, ParenTypeId, DeclaratorInfo,
Sebastian Redla55e52c2008-11-25 22:21:31 +0000756 ConstructorLParen, ConstructorArgs.take(),
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000757 ConstructorArgs.size(), ConstructorRParen);
758}
759
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000760/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
761/// passed to ParseDeclaratorInternal.
762///
763/// direct-new-declarator:
764/// '[' expression ']'
765/// direct-new-declarator '[' constant-expression ']'
766///
767void Parser::ParseDirectNewDeclarator(Declarator &D)
768{
769 // Parse the array dimensions.
770 bool first = true;
771 while (Tok.is(tok::l_square)) {
772 SourceLocation LLoc = ConsumeBracket();
773 ExprResult Size = first ? ParseExpression() : ParseConstantExpression();
774 if (Size.isInvalid) {
775 // Recover
776 SkipUntil(tok::r_square);
777 return;
778 }
779 first = false;
780
781 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
782 Size.Val, LLoc));
783
784 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
785 return;
786 }
787}
788
789/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
790/// This ambiguity appears in the syntax of the C++ new operator.
791///
792/// new-expression:
793/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
794/// new-initializer[opt]
795///
796/// new-placement:
797/// '(' expression-list ')'
798///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000799bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
800 Declarator &D)
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000801{
802 // The '(' was already consumed.
803 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000804 ParseSpecifierQualifierList(D.getMutableDeclSpec());
805 ParseDeclarator(D);
806 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000807 }
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}