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