ParseExprCXX.cpp revision 2f1bc5285ccd40f411af5f5993f013e27e74ab78
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"
17using namespace clang;
18
19/// ParseCXXCasts - This handles the various ways to cast expressions to another
20/// type.
21///
22///       postfix-expression: [C++ 5.2p1]
23///         'dynamic_cast' '<' type-name '>' '(' expression ')'
24///         'static_cast' '<' type-name '>' '(' expression ')'
25///         'reinterpret_cast' '<' type-name '>' '(' expression ')'
26///         'const_cast' '<' type-name '>' '(' expression ')'
27///
28Parser::ExprResult Parser::ParseCXXCasts() {
29  tok::TokenKind Kind = Tok.getKind();
30  const char *CastName = 0;     // For error messages
31
32  switch (Kind) {
33  default: assert(0 && "Unknown C++ cast!"); abort();
34  case tok::kw_const_cast:       CastName = "const_cast";       break;
35  case tok::kw_dynamic_cast:     CastName = "dynamic_cast";     break;
36  case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
37  case tok::kw_static_cast:      CastName = "static_cast";      break;
38  }
39
40  SourceLocation OpLoc = ConsumeToken();
41  SourceLocation LAngleBracketLoc = Tok.getLocation();
42
43  if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
44    return ExprResult(true);
45
46  TypeTy *CastTy = ParseTypeName();
47  SourceLocation RAngleBracketLoc = Tok.getLocation();
48
49  if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) {
50    Diag(LAngleBracketLoc, diag::err_matching, "<");
51    return ExprResult(true);
52  }
53
54  SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
55
56  if (Tok.isNot(tok::l_paren)) {
57    Diag(Tok, diag::err_expected_lparen_after, CastName);
58    return ExprResult(true);
59  }
60
61  ExprResult Result = ParseSimpleParenExpression(RParenLoc);
62
63  if (!Result.isInvalid)
64    Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
65                                       LAngleBracketLoc, CastTy, RAngleBracketLoc,
66                                       LParenLoc, Result.Val, RParenLoc);
67
68  return Result;
69}
70
71/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
72///
73///       boolean-literal: [C++ 2.13.5]
74///         'true'
75///         'false'
76Parser::ExprResult Parser::ParseCXXBoolLiteral() {
77  tok::TokenKind Kind = Tok.getKind();
78  return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
79}
80
81/// ParseThrowExpression - This handles the C++ throw expression.
82///
83///       throw-expression: [C++ 15]
84///         'throw' assignment-expression[opt]
85Parser::ExprResult Parser::ParseThrowExpression() {
86  assert(Tok.is(tok::kw_throw) && "Not throw!");
87  SourceLocation ThrowLoc = ConsumeToken();           // Eat the throw token.
88
89  // If the current token isn't the start of an assignment-expression,
90  // then the expression is not present.  This handles things like:
91  //   "C ? throw : (void)42", which is crazy but legal.
92  switch (Tok.getKind()) {  // FIXME: move this predicate somewhere common.
93  case tok::semi:
94  case tok::r_paren:
95  case tok::r_square:
96  case tok::r_brace:
97  case tok::colon:
98  case tok::comma:
99    return Actions.ActOnCXXThrow(ThrowLoc);
100
101  default:
102    ExprResult Expr = ParseAssignmentExpression();
103    if (Expr.isInvalid) return Expr;
104    return Actions.ActOnCXXThrow(ThrowLoc, Expr.Val);
105  }
106}
107
108/// ParseCXXThis - This handles the C++ 'this' pointer.
109///
110/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
111/// a non-lvalue expression whose value is the address of the object for which
112/// the function is called.
113Parser::ExprResult Parser::ParseCXXThis() {
114  assert(Tok.is(tok::kw_this) && "Not 'this'!");
115  SourceLocation ThisLoc = ConsumeToken();
116  return Actions.ActOnCXXThis(ThisLoc);
117}
118
119/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
120/// Can be interpreted either as function-style casting ("int(x)")
121/// or class type construction ("ClassType(x,y,z)")
122/// or creation of a value-initialized type ("int()").
123///
124///       postfix-expression: [C++ 5.2p1]
125///         simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
126///         typename-specifier '(' expression-list[opt] ')'         [TODO]
127///
128Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
129  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
130  TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
131
132  assert(Tok.is(tok::l_paren) && "Expected '('!");
133  SourceLocation LParenLoc = ConsumeParen();
134
135  ExprListTy Exprs;
136  CommaLocsTy CommaLocs;
137
138  if (Tok.isNot(tok::r_paren)) {
139    if (ParseExpressionList(Exprs, CommaLocs)) {
140      SkipUntil(tok::r_paren);
141      return ExprResult(true);
142    }
143  }
144
145  // Match the ')'.
146  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
147
148  assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
149         "Unexpected number of commas!");
150  return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
151                                           LParenLoc,
152                                           &Exprs[0], Exprs.size(),
153                                           &CommaLocs[0], RParenLoc);
154}
155
156/// ParseCXXCondition - if/switch/while/for condition expression.
157///
158///       condition:
159///         expression
160///         type-specifier-seq declarator '=' assignment-expression
161/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
162///             '=' assignment-expression
163///
164Parser::ExprResult Parser::ParseCXXCondition() {
165  if (!isCXXConditionDeclaration())
166    return ParseExpression(); // expression
167
168  SourceLocation StartLoc = Tok.getLocation();
169
170  // type-specifier-seq
171  DeclSpec DS;
172  ParseSpecifierQualifierList(DS);
173
174  // declarator
175  Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
176  ParseDeclarator(DeclaratorInfo);
177
178  // simple-asm-expr[opt]
179  if (Tok.is(tok::kw_asm)) {
180    ExprResult AsmLabel = ParseSimpleAsm();
181    if (AsmLabel.isInvalid) {
182      SkipUntil(tok::semi);
183      return true;
184    }
185    DeclaratorInfo.setAsmLabel(AsmLabel.Val);
186  }
187
188  // If attributes are present, parse them.
189  if (Tok.is(tok::kw___attribute))
190    DeclaratorInfo.AddAttributes(ParseAttributes());
191
192  // '=' assignment-expression
193  if (Tok.isNot(tok::equal))
194    return Diag(Tok, diag::err_expected_equal_after_declarator);
195  SourceLocation EqualLoc = ConsumeToken();
196  ExprResult AssignExpr = ParseAssignmentExpression();
197  if (AssignExpr.isInvalid)
198    return true;
199
200  return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
201                                                  DeclaratorInfo,
202                                                  EqualLoc, AssignExpr.Val);
203}
204
205/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
206/// This should only be called when the current token is known to be part of
207/// simple-type-specifier.
208///
209///       simple-type-specifier:
210///         '::'[opt] nested-name-specifier[opt] type-name                [TODO]
211///         '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
212///         char
213///         wchar_t
214///         bool
215///         short
216///         int
217///         long
218///         signed
219///         unsigned
220///         float
221///         double
222///         void
223/// [GNU]   typeof-specifier
224/// [C++0x] auto               [TODO]
225///
226///       type-name:
227///         class-name
228///         enum-name
229///         typedef-name
230///
231void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
232  DS.SetRangeStart(Tok.getLocation());
233  const char *PrevSpec;
234  SourceLocation Loc = Tok.getLocation();
235
236  switch (Tok.getKind()) {
237  default:
238    assert(0 && "Not a simple-type-specifier token!");
239    abort();
240
241  // type-name
242  case tok::identifier: {
243    TypeTy *TypeRep = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope);
244    assert(TypeRep && "Identifier wasn't a type-name!");
245    DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, TypeRep);
246    break;
247  }
248
249  // builtin types
250  case tok::kw_short:
251    DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
252    break;
253  case tok::kw_long:
254    DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
255    break;
256  case tok::kw_signed:
257    DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
258    break;
259  case tok::kw_unsigned:
260    DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
261    break;
262  case tok::kw_void:
263    DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
264    break;
265  case tok::kw_char:
266    DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
267    break;
268  case tok::kw_int:
269    DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
270    break;
271  case tok::kw_float:
272    DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
273    break;
274  case tok::kw_double:
275    DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
276    break;
277  case tok::kw_wchar_t:
278    DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
279    break;
280  case tok::kw_bool:
281    DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
282    break;
283
284  // GNU typeof support.
285  case tok::kw_typeof:
286    ParseTypeofSpecifier(DS);
287    DS.Finish(Diags, PP.getSourceManager(), getLang());
288    return;
289  }
290  DS.SetRangeEnd(Tok.getLocation());
291  ConsumeToken();
292  DS.Finish(Diags, PP.getSourceManager(), getLang());
293}
294
295/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
296/// [dcl.name]), which is a non-empty sequence of type-specifiers,
297/// e.g., "const short int". Note that the DeclSpec is *not* finished
298/// by parsing the type-specifier-seq, because these sequences are
299/// typically followed by some form of declarator. Returns true and
300/// emits diagnostics if this is not a type-specifier-seq, false
301/// otherwise.
302///
303///   type-specifier-seq: [C++ 8.1]
304///     type-specifier type-specifier-seq[opt]
305///
306bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
307  DS.SetRangeStart(Tok.getLocation());
308  const char *PrevSpec = 0;
309  int isInvalid = 0;
310
311  // Parse one or more of the type specifiers.
312  if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
313    Diag(Tok.getLocation(), diag::err_operator_missing_type_specifier);
314    return true;
315  }
316  while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec));
317
318  return false;
319}
320
321/// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded
322/// operator name (C++ [over.oper]). If successful, returns the
323/// predefined identifier that corresponds to that overloaded
324/// operator. Otherwise, returns NULL and does not consume any tokens.
325///
326///       operator-function-id: [C++ 13.5]
327///         'operator' operator
328///
329/// operator: one of
330///            new   delete  new[]   delete[]
331///            +     -    *  /    %  ^    &   |   ~
332///            !     =    <  >    += -=   *=  /=  %=
333///            ^=    &=   |= <<   >> >>= <<=  ==  !=
334///            <=    >=   && ||   ++ --   ,   ->* ->
335///            ()    []
336IdentifierInfo *Parser::MaybeParseOperatorFunctionId() {
337  assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
338
339  OverloadedOperatorKind Op = OO_None;
340  switch (NextToken().getKind()) {
341  case tok::kw_new:
342    ConsumeToken(); // 'operator'
343    ConsumeToken(); // 'new'
344    if (Tok.is(tok::l_square)) {
345      ConsumeBracket(); // '['
346      ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
347      Op = OO_Array_New;
348    } else {
349      Op = OO_New;
350    }
351    return &PP.getIdentifierTable().getOverloadedOperator(Op);
352
353  case tok::kw_delete:
354    ConsumeToken(); // 'operator'
355    ConsumeToken(); // 'delete'
356    if (Tok.is(tok::l_square)) {
357      ConsumeBracket(); // '['
358      ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
359      Op = OO_Array_Delete;
360    } else {
361      Op = OO_Delete;
362    }
363    return &PP.getIdentifierTable().getOverloadedOperator(Op);
364
365#define OVERLOADED_OPERATOR(Name,Spelling,Token) \
366    case tok::Token:  Op = OO_##Name; break;
367#define OVERLOADED_OPERATOR_MULTI(Name,Spelling)
368#include "clang/Basic/OperatorKinds.def"
369
370  case tok::l_paren:
371    ConsumeToken(); // 'operator'
372    ConsumeParen(); // '('
373    ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
374    return &PP.getIdentifierTable().getOverloadedOperator(OO_Call);
375
376  case tok::l_square:
377    ConsumeToken(); // 'operator'
378    ConsumeBracket(); // '['
379    ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
380    return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript);
381
382  default:
383    break;
384  }
385
386  if (Op == OO_None)
387    return 0;
388  else {
389    ConsumeToken(); // 'operator'
390    ConsumeAnyToken(); // the operator itself
391    return &PP.getIdentifierTable().getOverloadedOperator(Op);
392  }
393}
394
395/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
396/// which expresses the name of a user-defined conversion operator
397/// (C++ [class.conv.fct]p1). Returns the type that this operator is
398/// specifying a conversion for, or NULL if there was an error.
399///
400///        conversion-function-id: [C++ 12.3.2]
401///                   operator conversion-type-id
402///
403///        conversion-type-id:
404///                   type-specifier-seq conversion-declarator[opt]
405///
406///        conversion-declarator:
407///                   ptr-operator conversion-declarator[opt]
408Parser::TypeTy *Parser::ParseConversionFunctionId() {
409  assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
410  ConsumeToken(); // 'operator'
411
412  // Parse the type-specifier-seq.
413  DeclSpec DS;
414  if (ParseCXXTypeSpecifierSeq(DS))
415    return 0;
416
417  // Parse the conversion-declarator, which is merely a sequence of
418  // ptr-operators.
419  Declarator D(DS, Declarator::TypeNameContext);
420  ParseDeclaratorInternal(D, /*PtrOperator=*/true);
421
422  // Finish up the type.
423  Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
424  if (Result.isInvalid)
425    return 0;
426  else
427    return Result.Val;
428}
429