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