ParseExprCXX.cpp revision cee63fbf0e64ac526582312bf8cf33263fc5c16e
1//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
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"
16#include "clang/Parse/DeclSpec.h"
17#include "AstGuard.h"
18using namespace clang;
19
20/// MaybeParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
21/// Returns true if a nested-name-specifier was parsed from the token stream.
22///
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///
32bool 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;
40
41  if (Tok.is(tok::annot_cxxscope)) {
42    SS.setScopeRep(Tok.getAnnotationValue());
43    SS.setRange(Tok.getAnnotationRange());
44    ConsumeToken();
45    return true;
46  }
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  }
78
79  return true;
80}
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;
138  MaybeParseCXXScopeSpecifier(SS);
139
140  // unqualified-id:
141  //   identifier
142  //   operator-function-id
143  //   conversion-function-id
144  //   '~' 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();
161    if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
162      return Actions.ActOnCXXOperatorFunctionIdExpr(CurScope, OperatorLoc, Op,
163                                                    Tok.is(tok::l_paren), SS);
164    } else if (TypeTy *Type = ParseConversionFunctionId()) {
165      return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc,
166                                                    Type, Tok.is(tok::l_paren),
167                                                    SS);
168    }
169
170    // We already complained about a bad conversion-function-id,
171    // above.
172    return true;
173  }
174
175  } // switch.
176
177  assert(0 && "The switch was supposed to take care everything.");
178}
179
180/// 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
210  if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
211    return Diag(LAngleBracketLoc, diag::note_matching) << "<";
212
213  SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
214
215  if (Tok.isNot(tok::l_paren))
216    return Diag(Tok, diag::err_expected_lparen_after) << CastName;
217
218  ExprResult Result = ParseSimpleParenExpression(RParenLoc);
219
220  if (!Result.isInvalid)
221    Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
222                                       LAngleBracketLoc, CastTy, RAngleBracketLoc,
223                                       LParenLoc, Result.Val, RParenLoc);
224
225  return Result;
226}
227
228/// 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
276/// 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();
283  return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
284}
285
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!");
292  SourceLocation ThrowLoc = ConsumeToken();           // Eat the throw token.
293
294  // 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:
304    return Actions.ActOnCXXThrow(ThrowLoc);
305
306  default:
307    ExprResult Expr = ParseAssignmentExpression();
308    if (Expr.isInvalid) return Expr;
309    return Actions.ActOnCXXThrow(ThrowLoc, Expr.Val);
310  }
311}
312
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();
321  return Actions.ActOnCXXThis(ThisLoc);
322}
323
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
340  ExprVector Exprs(Actions);
341  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,
357                                           Exprs.take(), Exprs.size(),
358                                           &CommaLocs[0], RParenLoc);
359}
360
361/// 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() {
370  if (!isCXXConditionDeclaration())
371    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
410/// 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:
415///         '::'[opt] nested-name-specifier[opt] type-name
416///         '::'[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) {
437  // Annotate typenames and C++ scope specifiers.
438  TryAnnotateTypeOrScopeToken();
439
440  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
450  case tok::annot_qualtypename: {
451    DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
452                       Tok.getAnnotationValue());
453    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  }
497  if (Tok.is(tok::annot_qualtypename))
498    DS.SetRangeEnd(Tok.getAnnotationEndLoc());
499  else
500    DS.SetRangeEnd(Tok.getLocation());
501  ConsumeToken();
502  DS.Finish(Diags, PP.getSourceManager(), getLang());
503}
504
505/// 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)) {
523    Diag(Tok, diag::err_operator_missing_type_specifier);
524    return true;
525  }
526  while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
527
528  return false;
529}
530
531/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
532/// 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///            ()    []
546OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
547  assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
548
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    }
561    return Op;
562
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    }
573    return Op;
574
575#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)  \
576    case tok::Token:  Op = OO_##Name; break;
577#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
578#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); // ')'
584    return OO_Call;
585
586  case tok::l_square:
587    ConsumeToken(); // 'operator'
588    ConsumeBracket(); // '['
589    ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
590    return OO_Subscript;
591
592  default:
593    return OO_None;
594  }
595
596  ConsumeToken(); // 'operator'
597  ConsumeAnyToken(); // the operator itself
598  return Op;
599}
600
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);
626  ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
627
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}
635
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///
648///        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///
655///        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
678  ExprVector PlacementArgs(Actions);
679  SourceLocation PlacementLParen, PlacementRParen;
680
681  bool ParenTypeId;
682  DeclSpec DS;
683  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
684  if (Tok.is(tok::l_paren)) {
685    // If it turns out to be a placement, we change the type location.
686    PlacementLParen = ConsumeParen();
687    if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
688      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
689      return true;
690    }
691
692    PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
693    if (PlacementRParen.isInvalid()) {
694      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
695      return true;
696    }
697
698    if (PlacementArgs.empty()) {
699      // 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)) {
705        SourceLocation LParen = ConsumeParen();
706        ParseSpecifierQualifierList(DS);
707        ParseDeclarator(DeclaratorInfo);
708        MatchRHSPunctuation(tok::r_paren, LParen);
709        ParenTypeId = true;
710      } else {
711        if (ParseCXXTypeSpecifierSeq(DS))
712          DeclaratorInfo.setInvalidType(true);
713        else
714          ParseDeclaratorInternal(DeclaratorInfo,
715                                  &Parser::ParseDirectNewDeclarator);
716        ParenTypeId = false;
717      }
718    }
719  } else {
720    // 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);
727    ParenTypeId = false;
728  }
729  if (DeclaratorInfo.getInvalidType()) {
730    SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
731    return true;
732  }
733
734  ExprVector ConstructorArgs(Actions);
735  SourceLocation ConstructorLParen, ConstructorRParen;
736
737  if (Tok.is(tok::l_paren)) {
738    ConstructorLParen = ConsumeParen();
739    if (Tok.isNot(tok::r_paren)) {
740      CommaLocsTy CommaLocs;
741      if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
742        SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
743        return true;
744      }
745    }
746    ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
747    if (ConstructorRParen.isInvalid()) {
748      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
749      return true;
750    }
751  }
752
753  return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
754                             PlacementArgs.take(), PlacementArgs.size(),
755                             PlacementRParen, ParenTypeId, DeclaratorInfo,
756                             ConstructorLParen, ConstructorArgs.take(),
757                             ConstructorArgs.size(), ConstructorRParen);
758}
759
760/// 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///
799bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
800                                         Declarator &D)
801{
802  // The '(' was already consumed.
803  if (isTypeIdInParens()) {
804    ParseSpecifierQualifierList(D.getMutableDeclSpec());
805    ParseDeclarator(D);
806    return D.getInvalidType();
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}
853