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