ParseExprCXX.cpp revision 500d3297d2a21edeac4d46cbcbe21bc2352c2a28
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/Parse/ParseDiagnostic.h"
15#include "clang/Parse/Parser.h"
16#include "clang/Parse/DeclSpec.h"
17#include "AstGuard.h"
18using namespace clang;
19
20/// ParseOptionalCXXScopeSpecifier - Parse global scope or
21/// nested-name-specifier if present.  Returns true if a nested-name-specifier
22/// was parsed from the token stream.  Note that this routine will not parse
23/// ::new or ::delete, it will just leave them in the token stream.
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::ParseOptionalCXXScopeSpecifier(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  ParseOptionalCXXScopeSpecifier(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 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 Actions.ActOnCXXOperatorFunctionIdExpr(
165                   CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS);
166    if (TypeTy *Type = ParseConversionFunctionId())
167      return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
168                                                    Tok.is(tok::l_paren), SS);
169
170    // We already complained about a bad conversion-function-id,
171    // above.
172    return ExprError();
173  }
174
175  } // switch.
176
177  assert(0 && "The switch was supposed to take care everything.");
178}
179
180/// ParseCXXCasts - This handles the various ways to cast expressions to another
181/// type.
182///
183///       postfix-expression: [C++ 5.2p1]
184///         'dynamic_cast' '<' type-name '>' '(' expression ')'
185///         'static_cast' '<' type-name '>' '(' expression ')'
186///         'reinterpret_cast' '<' type-name '>' '(' expression ')'
187///         'const_cast' '<' type-name '>' '(' expression ')'
188///
189Parser::OwningExprResult Parser::ParseCXXCasts() {
190  tok::TokenKind Kind = Tok.getKind();
191  const char *CastName = 0;     // For error messages
192
193  switch (Kind) {
194  default: assert(0 && "Unknown C++ cast!"); abort();
195  case tok::kw_const_cast:       CastName = "const_cast";       break;
196  case tok::kw_dynamic_cast:     CastName = "dynamic_cast";     break;
197  case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
198  case tok::kw_static_cast:      CastName = "static_cast";      break;
199  }
200
201  SourceLocation OpLoc = ConsumeToken();
202  SourceLocation LAngleBracketLoc = Tok.getLocation();
203
204  if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
205    return ExprError();
206
207  TypeTy *CastTy = ParseTypeName();
208  SourceLocation RAngleBracketLoc = Tok.getLocation();
209
210  if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
211    return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
212
213  SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
214
215  if (Tok.isNot(tok::l_paren))
216    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
217
218  OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
219
220  if (!Result.isInvalid())
221    Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
222                                       LAngleBracketLoc, CastTy, RAngleBracketLoc,
223                                       LParenLoc, Result.release(), RParenLoc);
224
225  return move(Result);
226}
227
228/// ParseCXXTypeid - This handles the C++ typeid expression.
229///
230///       postfix-expression: [C++ 5.2p1]
231///         'typeid' '(' expression ')'
232///         'typeid' '(' type-id ')'
233///
234Parser::OwningExprResult Parser::ParseCXXTypeid() {
235  assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
236
237  SourceLocation OpLoc = ConsumeToken();
238  SourceLocation LParenLoc = Tok.getLocation();
239  SourceLocation RParenLoc;
240
241  // typeid expressions are always parenthesized.
242  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
243      "typeid"))
244    return ExprError();
245
246  OwningExprResult Result(Actions);
247
248  if (isTypeIdInParens()) {
249    TypeTy *Ty = ParseTypeName();
250
251    // Match the ')'.
252    MatchRHSPunctuation(tok::r_paren, LParenLoc);
253
254    if (!Ty)
255      return ExprError();
256
257    Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
258                                    Ty, RParenLoc);
259  } else {
260    Result = ParseExpression();
261
262    // Match the ')'.
263    if (Result.isInvalid())
264      SkipUntil(tok::r_paren);
265    else {
266      MatchRHSPunctuation(tok::r_paren, LParenLoc);
267
268      Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
269                                      Result.release(), RParenLoc);
270    }
271  }
272
273  return move(Result);
274}
275
276/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
277///
278///       boolean-literal: [C++ 2.13.5]
279///         'true'
280///         'false'
281Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
282  tok::TokenKind Kind = Tok.getKind();
283  return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
284}
285
286/// ParseThrowExpression - This handles the C++ throw expression.
287///
288///       throw-expression: [C++ 15]
289///         'throw' assignment-expression[opt]
290Parser::OwningExprResult Parser::ParseThrowExpression() {
291  assert(Tok.is(tok::kw_throw) && "Not throw!");
292  SourceLocation ThrowLoc = ConsumeToken();           // Eat the throw token.
293
294  // If the current token isn't the start of an assignment-expression,
295  // then the expression is not present.  This handles things like:
296  //   "C ? throw : (void)42", which is crazy but legal.
297  switch (Tok.getKind()) {  // FIXME: move this predicate somewhere common.
298  case tok::semi:
299  case tok::r_paren:
300  case tok::r_square:
301  case tok::r_brace:
302  case tok::colon:
303  case tok::comma:
304    return Owned(Actions.ActOnCXXThrow(ThrowLoc));
305
306  default:
307    OwningExprResult Expr(ParseAssignmentExpression());
308    if (Expr.isInvalid()) return move(Expr);
309    return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
310  }
311}
312
313/// ParseCXXThis - This handles the C++ 'this' pointer.
314///
315/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
316/// a non-lvalue expression whose value is the address of the object for which
317/// the function is called.
318Parser::OwningExprResult Parser::ParseCXXThis() {
319  assert(Tok.is(tok::kw_this) && "Not 'this'!");
320  SourceLocation ThisLoc = ConsumeToken();
321  return Owned(Actions.ActOnCXXThis(ThisLoc));
322}
323
324/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
325/// Can be interpreted either as function-style casting ("int(x)")
326/// or class type construction ("ClassType(x,y,z)")
327/// or creation of a value-initialized type ("int()").
328///
329///       postfix-expression: [C++ 5.2p1]
330///         simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
331///         typename-specifier '(' expression-list[opt] ')'         [TODO]
332///
333Parser::OwningExprResult
334Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
335  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
336  TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
337
338  assert(Tok.is(tok::l_paren) && "Expected '('!");
339  SourceLocation LParenLoc = ConsumeParen();
340
341  ExprVector Exprs(Actions);
342  CommaLocsTy CommaLocs;
343
344  if (Tok.isNot(tok::r_paren)) {
345    if (ParseExpressionList(Exprs, CommaLocs)) {
346      SkipUntil(tok::r_paren);
347      return ExprError();
348    }
349  }
350
351  // Match the ')'.
352  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
353
354  assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
355         "Unexpected number of commas!");
356  return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
357                                                 LParenLoc,
358                                                 Exprs.take(), Exprs.size(),
359                                                 &CommaLocs[0], RParenLoc));
360}
361
362/// ParseCXXCondition - if/switch/while/for condition expression.
363///
364///       condition:
365///         expression
366///         type-specifier-seq declarator '=' assignment-expression
367/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
368///             '=' assignment-expression
369///
370Parser::OwningExprResult Parser::ParseCXXCondition() {
371  if (!isCXXConditionDeclaration())
372    return ParseExpression(); // expression
373
374  SourceLocation StartLoc = Tok.getLocation();
375
376  // type-specifier-seq
377  DeclSpec DS;
378  ParseSpecifierQualifierList(DS);
379
380  // declarator
381  Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
382  ParseDeclarator(DeclaratorInfo);
383
384  // simple-asm-expr[opt]
385  if (Tok.is(tok::kw_asm)) {
386    OwningExprResult AsmLabel(ParseSimpleAsm());
387    if (AsmLabel.isInvalid()) {
388      SkipUntil(tok::semi);
389      return ExprError();
390    }
391    DeclaratorInfo.setAsmLabel(AsmLabel.release());
392  }
393
394  // If attributes are present, parse them.
395  if (Tok.is(tok::kw___attribute))
396    DeclaratorInfo.AddAttributes(ParseAttributes());
397
398  // '=' assignment-expression
399  if (Tok.isNot(tok::equal))
400    return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
401  SourceLocation EqualLoc = ConsumeToken();
402  OwningExprResult AssignExpr(ParseAssignmentExpression());
403  if (AssignExpr.isInvalid())
404    return ExprError();
405
406  return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
407                                                        DeclaratorInfo,EqualLoc,
408                                                        AssignExpr.release()));
409}
410
411/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
412/// This should only be called when the current token is known to be part of
413/// simple-type-specifier.
414///
415///       simple-type-specifier:
416///         '::'[opt] nested-name-specifier[opt] type-name
417///         '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
418///         char
419///         wchar_t
420///         bool
421///         short
422///         int
423///         long
424///         signed
425///         unsigned
426///         float
427///         double
428///         void
429/// [GNU]   typeof-specifier
430/// [C++0x] auto               [TODO]
431///
432///       type-name:
433///         class-name
434///         enum-name
435///         typedef-name
436///
437void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
438  DS.SetRangeStart(Tok.getLocation());
439  const char *PrevSpec;
440  SourceLocation Loc = Tok.getLocation();
441
442  switch (Tok.getKind()) {
443  case tok::identifier:   // foo::bar
444  case tok::coloncolon:   // ::foo::bar
445    assert(0 && "Annotation token should already be formed!");
446  default:
447    assert(0 && "Not a simple-type-specifier token!");
448    abort();
449
450  // type-name
451  case tok::annot_typename: {
452    DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
453                       Tok.getAnnotationValue());
454    break;
455  }
456
457  // builtin types
458  case tok::kw_short:
459    DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
460    break;
461  case tok::kw_long:
462    DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
463    break;
464  case tok::kw_signed:
465    DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
466    break;
467  case tok::kw_unsigned:
468    DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
469    break;
470  case tok::kw_void:
471    DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
472    break;
473  case tok::kw_char:
474    DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
475    break;
476  case tok::kw_int:
477    DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
478    break;
479  case tok::kw_float:
480    DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
481    break;
482  case tok::kw_double:
483    DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
484    break;
485  case tok::kw_wchar_t:
486    DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
487    break;
488  case tok::kw_bool:
489    DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
490    break;
491
492  // GNU typeof support.
493  case tok::kw_typeof:
494    ParseTypeofSpecifier(DS);
495    DS.Finish(Diags, PP.getSourceManager(), getLang());
496    return;
497  }
498  if (Tok.is(tok::annot_typename))
499    DS.SetRangeEnd(Tok.getAnnotationEndLoc());
500  else
501    DS.SetRangeEnd(Tok.getLocation());
502  ConsumeToken();
503  DS.Finish(Diags, PP.getSourceManager(), getLang());
504}
505
506/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
507/// [dcl.name]), which is a non-empty sequence of type-specifiers,
508/// e.g., "const short int". Note that the DeclSpec is *not* finished
509/// by parsing the type-specifier-seq, because these sequences are
510/// typically followed by some form of declarator. Returns true and
511/// emits diagnostics if this is not a type-specifier-seq, false
512/// otherwise.
513///
514///   type-specifier-seq: [C++ 8.1]
515///     type-specifier type-specifier-seq[opt]
516///
517bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
518  DS.SetRangeStart(Tok.getLocation());
519  const char *PrevSpec = 0;
520  int isInvalid = 0;
521
522  // Parse one or more of the type specifiers.
523  if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) {
524    Diag(Tok, diag::err_operator_missing_type_specifier);
525    return true;
526  }
527
528  while (ParseOptionalTypeSpecifier(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.get();
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
843static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
844{
845  switch(kind) {
846  default: assert(false && "Not a known unary type trait.");
847  case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
848  case tok::kw___has_nothrow_copy:        return UTT_HasNothrowCopy;
849  case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
850  case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign;
851  case tok::kw___has_trivial_copy:        return UTT_HasTrivialCopy;
852  case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
853  case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor;
854  case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor;
855  case tok::kw___is_abstract:             return UTT_IsAbstract;
856  case tok::kw___is_class:                return UTT_IsClass;
857  case tok::kw___is_empty:                return UTT_IsEmpty;
858  case tok::kw___is_enum:                 return UTT_IsEnum;
859  case tok::kw___is_pod:                  return UTT_IsPOD;
860  case tok::kw___is_polymorphic:          return UTT_IsPolymorphic;
861  case tok::kw___is_union:                return UTT_IsUnion;
862  }
863}
864
865/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
866/// pseudo-functions that allow implementation of the TR1/C++0x type traits
867/// templates.
868///
869///       primary-expression:
870/// [GNU]             unary-type-trait '(' type-id ')'
871///
872Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
873{
874  UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
875  SourceLocation Loc = ConsumeToken();
876
877  SourceLocation LParen = Tok.getLocation();
878  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
879    return ExprError();
880
881  // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
882  // there will be cryptic errors about mismatched parentheses and missing
883  // specifiers.
884  TypeTy *Ty = ParseTypeName();
885
886  SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
887
888  return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty, RParen);
889}
890