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