blob: 68964e91ee6f833ba2397b7839e9a21360add47a [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Expression parsing implementation for C++.
11//
12//===----------------------------------------------------------------------===//
13
Chris Lattner500d3292009-01-29 05:15:15 +000014#include "clang/Parse/ParseDiagnostic.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000015#include "clang/Parse/Parser.h"
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +000016#include "clang/Parse/DeclSpec.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000017using namespace clang;
18
Chris Lattner7a0ab5f2009-01-06 06:59:53 +000019/// ParseOptionalCXXScopeSpecifier - Parse global scope or
20/// nested-name-specifier if present. Returns true if a nested-name-specifier
21/// was parsed from the token stream. Note that this routine will not parse
22/// ::new or ::delete, it will just leave them in the token stream.
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000023///
24/// '::'[opt] nested-name-specifier
25/// '::'
26///
27/// nested-name-specifier:
28/// type-name '::'
29/// namespace-name '::'
30/// nested-name-specifier identifier '::'
31/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
32///
Chris Lattner7a0ab5f2009-01-06 06:59:53 +000033bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000034 assert(getLang().CPlusPlus &&
Chris Lattner7452c6f2009-01-05 01:24:05 +000035 "Call sites of this function should be guarded by checking for C++");
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000036
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000037 if (Tok.is(tok::annot_cxxscope)) {
Douglas Gregor35073692009-03-26 23:56:24 +000038 SS.setScopeRep(Tok.getAnnotationValue());
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000039 SS.setRange(Tok.getAnnotationRange());
40 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000041 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000042 }
Chris Lattnere607e802009-01-04 21:14:15 +000043
Douglas Gregor39a8de12009-02-25 19:37:18 +000044 bool HasScopeSpecifier = false;
45
Chris Lattner5b454732009-01-05 03:55:46 +000046 if (Tok.is(tok::coloncolon)) {
47 // ::new and ::delete aren't nested-name-specifiers.
48 tok::TokenKind NextKind = NextToken().getKind();
49 if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
50 return false;
Chris Lattner55a7cef2009-01-05 00:13:00 +000051
Chris Lattner55a7cef2009-01-05 00:13:00 +000052 // '::' - Global scope qualifier.
Chris Lattner357089d2009-01-05 02:07:19 +000053 SourceLocation CCLoc = ConsumeToken();
Chris Lattner357089d2009-01-05 02:07:19 +000054 SS.setBeginLoc(CCLoc);
Douglas Gregor35073692009-03-26 23:56:24 +000055 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
Chris Lattner357089d2009-01-05 02:07:19 +000056 SS.setEndLoc(CCLoc);
Douglas Gregor39a8de12009-02-25 19:37:18 +000057 HasScopeSpecifier = true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000058 }
59
Douglas Gregor39a8de12009-02-25 19:37:18 +000060 while (true) {
61 // nested-name-specifier:
Chris Lattner77cf72a2009-06-26 03:47:46 +000062 // nested-name-specifier 'template'[opt] simple-template-id '::'
63
64 // Parse the optional 'template' keyword, then make sure we have
65 // 'identifier <' after it.
66 if (Tok.is(tok::kw_template)) {
67 SourceLocation TemplateKWLoc = ConsumeToken();
68
69 if (Tok.isNot(tok::identifier)) {
70 Diag(Tok.getLocation(),
71 diag::err_id_after_template_in_nested_name_spec)
72 << SourceRange(TemplateKWLoc);
73 break;
74 }
75
76 if (NextToken().isNot(tok::less)) {
77 Diag(NextToken().getLocation(),
78 diag::err_less_after_template_name_in_nested_name_spec)
79 << Tok.getIdentifierInfo()->getName()
80 << SourceRange(TemplateKWLoc, Tok.getLocation());
81 break;
82 }
83
84 TemplateTy Template
85 = Actions.ActOnDependentTemplateName(TemplateKWLoc,
86 *Tok.getIdentifierInfo(),
87 Tok.getLocation(), SS);
88 AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
89 &SS, TemplateKWLoc, false);
90 continue;
91 }
92
Douglas Gregor39a8de12009-02-25 19:37:18 +000093 if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
94 // We have
95 //
96 // simple-template-id '::'
97 //
98 // So we need to check whether the simple-template-id is of the
Douglas Gregorc45c2322009-03-31 00:43:58 +000099 // right kind (it should name a type or be dependent), and then
100 // convert it into a type within the nested-name-specifier.
Douglas Gregor39a8de12009-02-25 19:37:18 +0000101 TemplateIdAnnotation *TemplateId
102 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
103
Douglas Gregorc45c2322009-03-31 00:43:58 +0000104 if (TemplateId->Kind == TNK_Type_template ||
105 TemplateId->Kind == TNK_Dependent_template_name) {
Douglas Gregor31a19b62009-04-01 21:51:26 +0000106 AnnotateTemplateIdTokenAsType(&SS);
Douglas Gregor3f5b61c2009-05-14 00:28:11 +0000107 SS.setScopeRep(0);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000108
109 assert(Tok.is(tok::annot_typename) &&
110 "AnnotateTemplateIdTokenAsType isn't working");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000111 Token TypeToken = Tok;
112 ConsumeToken();
113 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
114 SourceLocation CCLoc = ConsumeToken();
115
116 if (!HasScopeSpecifier) {
117 SS.setBeginLoc(TypeToken.getLocation());
118 HasScopeSpecifier = true;
119 }
Douglas Gregor31a19b62009-04-01 21:51:26 +0000120
121 if (TypeToken.getAnnotationValue())
122 SS.setScopeRep(
123 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
124 TypeToken.getAnnotationValue(),
125 TypeToken.getAnnotationRange(),
126 CCLoc));
127 else
128 SS.setScopeRep(0);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000129 SS.setEndLoc(CCLoc);
130 continue;
Chris Lattner67b9e832009-06-26 03:45:46 +0000131 }
132
133 assert(false && "FIXME: Only type template names supported here");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000134 }
135
Chris Lattner5c7f7862009-06-26 03:52:38 +0000136
137 // The rest of the nested-name-specifier possibilities start with
138 // tok::identifier.
139 if (Tok.isNot(tok::identifier))
140 break;
141
142 IdentifierInfo &II = *Tok.getIdentifierInfo();
143
144 // nested-name-specifier:
145 // type-name '::'
146 // namespace-name '::'
147 // nested-name-specifier identifier '::'
148 Token Next = NextToken();
149 if (Next.is(tok::coloncolon)) {
150 // We have an identifier followed by a '::'. Lookup this name
151 // as the name in a nested-name-specifier.
152 SourceLocation IdLoc = ConsumeToken();
153 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
154 SourceLocation CCLoc = ConsumeToken();
155
156 if (!HasScopeSpecifier) {
157 SS.setBeginLoc(IdLoc);
158 HasScopeSpecifier = true;
159 }
160
161 if (SS.isInvalid())
162 continue;
163
164 SS.setScopeRep(
165 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II));
166 SS.setEndLoc(CCLoc);
167 continue;
168 }
169
170 // nested-name-specifier:
171 // type-name '<'
172 if (Next.is(tok::less)) {
173 TemplateTy Template;
174 if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope,
175 Template, &SS)) {
176 // We have found a template name, so annotate this this token
177 // with a template-id annotation. We do not permit the
178 // template-id to be translated into a type annotation,
179 // because some clients (e.g., the parsing of class template
180 // specializations) still want to see the original template-id
181 // token.
182 AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), false);
183 continue;
184 }
185 }
186
Douglas Gregor39a8de12009-02-25 19:37:18 +0000187 // We don't have any tokens that form the beginning of a
188 // nested-name-specifier, so we're done.
189 break;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000190 }
Douglas Gregor39a8de12009-02-25 19:37:18 +0000191
192 return HasScopeSpecifier;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000193}
194
195/// ParseCXXIdExpression - Handle id-expression.
196///
197/// id-expression:
198/// unqualified-id
199/// qualified-id
200///
201/// unqualified-id:
202/// identifier
203/// operator-function-id
204/// conversion-function-id [TODO]
205/// '~' class-name [TODO]
206/// template-id [TODO]
207///
208/// qualified-id:
209/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
210/// '::' identifier
211/// '::' operator-function-id
212/// '::' template-id [TODO]
213///
214/// nested-name-specifier:
215/// type-name '::'
216/// namespace-name '::'
217/// nested-name-specifier identifier '::'
218/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
219///
220/// NOTE: The standard specifies that, for qualified-id, the parser does not
221/// expect:
222///
223/// '::' conversion-function-id
224/// '::' '~' class-name
225///
226/// This may cause a slight inconsistency on diagnostics:
227///
228/// class C {};
229/// namespace A {}
230/// void f() {
231/// :: A :: ~ C(); // Some Sema error about using destructor with a
232/// // namespace.
233/// :: ~ C(); // Some Parser error like 'unexpected ~'.
234/// }
235///
236/// We simplify the parser a bit and make it work like:
237///
238/// qualified-id:
239/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
240/// '::' unqualified-id
241///
242/// That way Sema can handle and report similar errors for namespaces and the
243/// global scope.
244///
Sebastian Redlebc07d52009-02-03 20:19:35 +0000245/// The isAddressOfOperand parameter indicates that this id-expression is a
246/// direct operand of the address-of operator. This is, besides member contexts,
247/// the only place where a qualified-id naming a non-static class member may
248/// appear.
249///
250Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000251 // qualified-id:
252 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
253 // '::' unqualified-id
254 //
255 CXXScopeSpec SS;
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000256 ParseOptionalCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000257
258 // unqualified-id:
259 // identifier
260 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000261 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000262 // '~' class-name [TODO]
263 // template-id [TODO]
264 //
265 switch (Tok.getKind()) {
266 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000267 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000268
269 case tok::identifier: {
270 // Consume the identifier so that we can see if it is followed by a '('.
271 IdentifierInfo &II = *Tok.getIdentifierInfo();
272 SourceLocation L = ConsumeToken();
Sebastian Redlebc07d52009-02-03 20:19:35 +0000273 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
274 &SS, isAddressOfOperand);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000275 }
276
277 case tok::kw_operator: {
278 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000279 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000280 return Actions.ActOnCXXOperatorFunctionIdExpr(
Sebastian Redlebc07d52009-02-03 20:19:35 +0000281 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
282 isAddressOfOperand);
Chris Lattner7452c6f2009-01-05 01:24:05 +0000283 if (TypeTy *Type = ParseConversionFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000284 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
Sebastian Redlebc07d52009-02-03 20:19:35 +0000285 Tok.is(tok::l_paren), SS,
286 isAddressOfOperand);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000287
Douglas Gregor2def4832008-11-17 20:34:05 +0000288 // We already complained about a bad conversion-function-id,
289 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000290 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000291 }
292
293 } // switch.
294
295 assert(0 && "The switch was supposed to take care everything.");
296}
297
Reid Spencer5f016e22007-07-11 17:01:13 +0000298/// ParseCXXCasts - This handles the various ways to cast expressions to another
299/// type.
300///
301/// postfix-expression: [C++ 5.2p1]
302/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
303/// 'static_cast' '<' type-name '>' '(' expression ')'
304/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
305/// 'const_cast' '<' type-name '>' '(' expression ')'
306///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000307Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000308 tok::TokenKind Kind = Tok.getKind();
309 const char *CastName = 0; // For error messages
310
311 switch (Kind) {
312 default: assert(0 && "Unknown C++ cast!"); abort();
313 case tok::kw_const_cast: CastName = "const_cast"; break;
314 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
315 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
316 case tok::kw_static_cast: CastName = "static_cast"; break;
317 }
318
319 SourceLocation OpLoc = ConsumeToken();
320 SourceLocation LAngleBracketLoc = Tok.getLocation();
321
322 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000323 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000324
Douglas Gregor809070a2009-02-18 17:45:20 +0000325 TypeResult CastTy = ParseTypeName();
Reid Spencer5f016e22007-07-11 17:01:13 +0000326 SourceLocation RAngleBracketLoc = Tok.getLocation();
327
Chris Lattner1ab3b962008-11-18 07:48:38 +0000328 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000329 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000330
331 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
332
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000333 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
334 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000335
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000336 OwningExprResult Result = ParseExpression();
337
338 // Match the ')'.
339 if (Result.isInvalid())
340 SkipUntil(tok::r_paren);
341
342 if (Tok.is(tok::r_paren))
343 RParenLoc = ConsumeParen();
344 else
345 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000346
Douglas Gregor809070a2009-02-18 17:45:20 +0000347 if (!Result.isInvalid() && !CastTy.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000348 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000349 LAngleBracketLoc, CastTy.get(),
Douglas Gregor809070a2009-02-18 17:45:20 +0000350 RAngleBracketLoc,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000351 LParenLoc, move(Result), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000352
Sebastian Redl20df9b72008-12-11 22:51:44 +0000353 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000354}
355
Sebastian Redlc42e1182008-11-11 11:37:55 +0000356/// ParseCXXTypeid - This handles the C++ typeid expression.
357///
358/// postfix-expression: [C++ 5.2p1]
359/// 'typeid' '(' expression ')'
360/// 'typeid' '(' type-id ')'
361///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000362Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000363 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
364
365 SourceLocation OpLoc = ConsumeToken();
366 SourceLocation LParenLoc = Tok.getLocation();
367 SourceLocation RParenLoc;
368
369 // typeid expressions are always parenthesized.
370 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
371 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000372 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000373
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000374 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000375
376 if (isTypeIdInParens()) {
Douglas Gregor809070a2009-02-18 17:45:20 +0000377 TypeResult Ty = ParseTypeName();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000378
379 // Match the ')'.
380 MatchRHSPunctuation(tok::r_paren, LParenLoc);
381
Douglas Gregor809070a2009-02-18 17:45:20 +0000382 if (Ty.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000383 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000384
385 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Douglas Gregor809070a2009-02-18 17:45:20 +0000386 Ty.get(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000387 } else {
Douglas Gregore0762c92009-06-19 23:52:42 +0000388 // C++0x [expr.typeid]p3:
389 // When typeid is applied to an expression other than an lvalue of a
390 // polymorphic class type [...] The expression is an unevaluated
391 // operand (Clause 5).
392 //
393 // Note that we can't tell whether the expression is an lvalue of a
394 // polymorphic class type until after we've parsed the expression, so
Douglas Gregorac7610d2009-06-22 20:57:11 +0000395 // we the expression is potentially potentially evaluated.
396 EnterExpressionEvaluationContext Unevaluated(Actions,
397 Action::PotentiallyPotentiallyEvaluated);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000398 Result = ParseExpression();
399
400 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000401 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000402 SkipUntil(tok::r_paren);
403 else {
404 MatchRHSPunctuation(tok::r_paren, LParenLoc);
405
406 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000407 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000408 }
409 }
410
Sebastian Redl20df9b72008-12-11 22:51:44 +0000411 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000412}
413
Reid Spencer5f016e22007-07-11 17:01:13 +0000414/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
415///
416/// boolean-literal: [C++ 2.13.5]
417/// 'true'
418/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000419Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000420 tok::TokenKind Kind = Tok.getKind();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000421 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Reid Spencer5f016e22007-07-11 17:01:13 +0000422}
Chris Lattner50dd2892008-02-26 00:51:44 +0000423
424/// ParseThrowExpression - This handles the C++ throw expression.
425///
426/// throw-expression: [C++ 15]
427/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000428Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000429 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000430 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000431
Chris Lattner2a2819a2008-04-06 06:02:23 +0000432 // If the current token isn't the start of an assignment-expression,
433 // then the expression is not present. This handles things like:
434 // "C ? throw : (void)42", which is crazy but legal.
435 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
436 case tok::semi:
437 case tok::r_paren:
438 case tok::r_square:
439 case tok::r_brace:
440 case tok::colon:
441 case tok::comma:
Sebastian Redlf53597f2009-03-15 17:47:39 +0000442 return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
Chris Lattner50dd2892008-02-26 00:51:44 +0000443
Chris Lattner2a2819a2008-04-06 06:02:23 +0000444 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000445 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000446 if (Expr.isInvalid()) return move(Expr);
Sebastian Redlf53597f2009-03-15 17:47:39 +0000447 return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000448 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000449}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000450
451/// ParseCXXThis - This handles the C++ 'this' pointer.
452///
453/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
454/// a non-lvalue expression whose value is the address of the object for which
455/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000456Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000457 assert(Tok.is(tok::kw_this) && "Not 'this'!");
458 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000459 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000460}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000461
462/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
463/// Can be interpreted either as function-style casting ("int(x)")
464/// or class type construction ("ClassType(x,y,z)")
465/// or creation of a value-initialized type ("int()").
466///
467/// postfix-expression: [C++ 5.2p1]
468/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
469/// typename-specifier '(' expression-list[opt] ')' [TODO]
470///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000471Parser::OwningExprResult
472Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000473 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000474 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000475
476 assert(Tok.is(tok::l_paren) && "Expected '('!");
477 SourceLocation LParenLoc = ConsumeParen();
478
Sebastian Redla55e52c2008-11-25 22:21:31 +0000479 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000480 CommaLocsTy CommaLocs;
481
482 if (Tok.isNot(tok::r_paren)) {
483 if (ParseExpressionList(Exprs, CommaLocs)) {
484 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000485 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000486 }
487 }
488
489 // Match the ')'.
490 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
491
492 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
493 "Unexpected number of commas!");
Sebastian Redlf53597f2009-03-15 17:47:39 +0000494 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
495 LParenLoc, move_arg(Exprs),
Jay Foadbeaaccd2009-05-21 09:52:38 +0000496 CommaLocs.data(), RParenLoc);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000497}
498
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000499/// ParseCXXCondition - if/switch/while/for condition expression.
500///
501/// condition:
502/// expression
503/// type-specifier-seq declarator '=' assignment-expression
504/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
505/// '=' assignment-expression
506///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000507Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000508 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000509 return ParseExpression(); // expression
510
511 SourceLocation StartLoc = Tok.getLocation();
512
513 // type-specifier-seq
514 DeclSpec DS;
515 ParseSpecifierQualifierList(DS);
516
517 // declarator
518 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
519 ParseDeclarator(DeclaratorInfo);
520
521 // simple-asm-expr[opt]
522 if (Tok.is(tok::kw_asm)) {
Sebastian Redlab197ba2009-02-09 18:23:29 +0000523 SourceLocation Loc;
524 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000525 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000526 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000527 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000528 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000529 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000530 DeclaratorInfo.SetRangeEnd(Loc);
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000531 }
532
533 // If attributes are present, parse them.
Sebastian Redlab197ba2009-02-09 18:23:29 +0000534 if (Tok.is(tok::kw___attribute)) {
535 SourceLocation Loc;
536 AttributeList *AttrList = ParseAttributes(&Loc);
537 DeclaratorInfo.AddAttributes(AttrList, Loc);
538 }
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000539
540 // '=' assignment-expression
541 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000542 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000543 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000544 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000545 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000546 return ExprError();
547
Sebastian Redlf53597f2009-03-15 17:47:39 +0000548 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
549 DeclaratorInfo,EqualLoc,
550 move(AssignExpr));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000551}
552
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000553/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
554/// This should only be called when the current token is known to be part of
555/// simple-type-specifier.
556///
557/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000558/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000559/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
560/// char
561/// wchar_t
562/// bool
563/// short
564/// int
565/// long
566/// signed
567/// unsigned
568/// float
569/// double
570/// void
571/// [GNU] typeof-specifier
572/// [C++0x] auto [TODO]
573///
574/// type-name:
575/// class-name
576/// enum-name
577/// typedef-name
578///
579void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
580 DS.SetRangeStart(Tok.getLocation());
581 const char *PrevSpec;
582 SourceLocation Loc = Tok.getLocation();
583
584 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000585 case tok::identifier: // foo::bar
586 case tok::coloncolon: // ::foo::bar
587 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000588 default:
589 assert(0 && "Not a simple-type-specifier token!");
590 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000591
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000592 // type-name
Chris Lattnerb31757b2009-01-06 05:06:21 +0000593 case tok::annot_typename: {
Douglas Gregor1a51b4a2009-02-09 15:09:02 +0000594 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000595 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000596 break;
597 }
598
599 // builtin types
600 case tok::kw_short:
601 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
602 break;
603 case tok::kw_long:
604 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
605 break;
606 case tok::kw_signed:
607 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
608 break;
609 case tok::kw_unsigned:
610 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
611 break;
612 case tok::kw_void:
613 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
614 break;
615 case tok::kw_char:
616 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
617 break;
618 case tok::kw_int:
619 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
620 break;
621 case tok::kw_float:
622 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
623 break;
624 case tok::kw_double:
625 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
626 break;
627 case tok::kw_wchar_t:
628 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
629 break;
630 case tok::kw_bool:
631 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
632 break;
633
634 // GNU typeof support.
635 case tok::kw_typeof:
636 ParseTypeofSpecifier(DS);
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000637 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000638 return;
639 }
Chris Lattnerb31757b2009-01-06 05:06:21 +0000640 if (Tok.is(tok::annot_typename))
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000641 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
642 else
643 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000644 ConsumeToken();
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000645 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000646}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000647
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000648/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
649/// [dcl.name]), which is a non-empty sequence of type-specifiers,
650/// e.g., "const short int". Note that the DeclSpec is *not* finished
651/// by parsing the type-specifier-seq, because these sequences are
652/// typically followed by some form of declarator. Returns true and
653/// emits diagnostics if this is not a type-specifier-seq, false
654/// otherwise.
655///
656/// type-specifier-seq: [C++ 8.1]
657/// type-specifier type-specifier-seq[opt]
658///
659bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
660 DS.SetRangeStart(Tok.getLocation());
661 const char *PrevSpec = 0;
662 int isInvalid = 0;
663
664 // Parse one or more of the type specifiers.
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000665 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000666 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000667 return true;
668 }
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000669
Ted Kremenekb8006e52009-01-06 19:17:58 +0000670 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000671
672 return false;
673}
674
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000675/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000676/// operator name (C++ [over.oper]). If successful, returns the
677/// predefined identifier that corresponds to that overloaded
678/// operator. Otherwise, returns NULL and does not consume any tokens.
679///
680/// operator-function-id: [C++ 13.5]
681/// 'operator' operator
682///
683/// operator: one of
684/// new delete new[] delete[]
685/// + - * / % ^ & | ~
686/// ! = < > += -= *= /= %=
687/// ^= &= |= << >> >>= <<= == !=
688/// <= >= && || ++ -- , ->* ->
689/// () []
Sebastian Redlab197ba2009-02-09 18:23:29 +0000690OverloadedOperatorKind
691Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000692 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Sebastian Redlab197ba2009-02-09 18:23:29 +0000693 SourceLocation Loc;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000694
695 OverloadedOperatorKind Op = OO_None;
696 switch (NextToken().getKind()) {
697 case tok::kw_new:
698 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000699 Loc = ConsumeToken(); // 'new'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000700 if (Tok.is(tok::l_square)) {
701 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000702 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000703 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
704 Op = OO_Array_New;
705 } else {
706 Op = OO_New;
707 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000708 if (EndLoc)
709 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000710 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000711
712 case tok::kw_delete:
713 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000714 Loc = ConsumeToken(); // 'delete'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000715 if (Tok.is(tok::l_square)) {
716 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000717 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000718 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
719 Op = OO_Array_Delete;
720 } else {
721 Op = OO_Delete;
722 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000723 if (EndLoc)
724 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000725 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000726
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000727#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000728 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000729#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000730#include "clang/Basic/OperatorKinds.def"
731
732 case tok::l_paren:
733 ConsumeToken(); // 'operator'
734 ConsumeParen(); // '('
Sebastian Redlab197ba2009-02-09 18:23:29 +0000735 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000736 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000737 if (EndLoc)
738 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000739 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000740
741 case tok::l_square:
742 ConsumeToken(); // 'operator'
743 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000744 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000745 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000746 if (EndLoc)
747 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000748 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000749
750 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000751 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000752 }
753
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000754 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000755 Loc = ConsumeAnyToken(); // the operator itself
756 if (EndLoc)
757 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000758 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000759}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000760
761/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
762/// which expresses the name of a user-defined conversion operator
763/// (C++ [class.conv.fct]p1). Returns the type that this operator is
764/// specifying a conversion for, or NULL if there was an error.
765///
766/// conversion-function-id: [C++ 12.3.2]
767/// operator conversion-type-id
768///
769/// conversion-type-id:
770/// type-specifier-seq conversion-declarator[opt]
771///
772/// conversion-declarator:
773/// ptr-operator conversion-declarator[opt]
Sebastian Redlab197ba2009-02-09 18:23:29 +0000774Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000775 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
776 ConsumeToken(); // 'operator'
777
778 // Parse the type-specifier-seq.
779 DeclSpec DS;
780 if (ParseCXXTypeSpecifierSeq(DS))
781 return 0;
782
783 // Parse the conversion-declarator, which is merely a sequence of
784 // ptr-operators.
785 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000786 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000787 if (EndLoc)
788 *EndLoc = D.getSourceRange().getEnd();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000789
790 // Finish up the type.
791 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000792 if (Result.isInvalid())
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000793 return 0;
794 else
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000795 return Result.get();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000796}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000797
798/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
799/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000800///
801/// This method is called to parse the new expression after the optional :: has
802/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
803/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000804///
805/// new-expression:
806/// '::'[opt] 'new' new-placement[opt] new-type-id
807/// new-initializer[opt]
808/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
809/// new-initializer[opt]
810///
811/// new-placement:
812/// '(' expression-list ')'
813///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000814/// new-type-id:
815/// type-specifier-seq new-declarator[opt]
816///
817/// new-declarator:
818/// ptr-operator new-declarator[opt]
819/// direct-new-declarator
820///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000821/// new-initializer:
822/// '(' expression-list[opt] ')'
823/// [C++0x] braced-init-list [TODO]
824///
Chris Lattner59232d32009-01-04 21:25:24 +0000825Parser::OwningExprResult
826Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
827 assert(Tok.is(tok::kw_new) && "expected 'new' token");
828 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000829
830 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
831 // second form of new-expression. It can't be a new-type-id.
832
Sebastian Redla55e52c2008-11-25 22:21:31 +0000833 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000834 SourceLocation PlacementLParen, PlacementRParen;
835
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000836 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000837 DeclSpec DS;
838 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000839 if (Tok.is(tok::l_paren)) {
840 // If it turns out to be a placement, we change the type location.
841 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000842 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
843 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000844 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000845 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000846
847 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000848 if (PlacementRParen.isInvalid()) {
849 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000850 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000851 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000852
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000853 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000854 // Reset the placement locations. There was no placement.
855 PlacementLParen = PlacementRParen = SourceLocation();
856 ParenTypeId = true;
857 } else {
858 // We still need the type.
859 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000860 SourceLocation LParen = ConsumeParen();
861 ParseSpecifierQualifierList(DS);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000862 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000863 ParseDeclarator(DeclaratorInfo);
864 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000865 ParenTypeId = true;
866 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000867 if (ParseCXXTypeSpecifierSeq(DS))
868 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000869 else {
870 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000871 ParseDeclaratorInternal(DeclaratorInfo,
872 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000873 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000874 ParenTypeId = false;
875 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000876 }
877 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000878 // A new-type-id is a simplified type-id, where essentially the
879 // direct-declarator is replaced by a direct-new-declarator.
880 if (ParseCXXTypeSpecifierSeq(DS))
881 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000882 else {
883 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000884 ParseDeclaratorInternal(DeclaratorInfo,
885 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000886 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000887 ParenTypeId = false;
888 }
Chris Lattnereaaebc72009-04-25 08:06:05 +0000889 if (DeclaratorInfo.isInvalidType()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000890 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000891 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000892 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000893
Sebastian Redla55e52c2008-11-25 22:21:31 +0000894 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000895 SourceLocation ConstructorLParen, ConstructorRParen;
896
897 if (Tok.is(tok::l_paren)) {
898 ConstructorLParen = ConsumeParen();
899 if (Tok.isNot(tok::r_paren)) {
900 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000901 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
902 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000903 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000904 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000905 }
906 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000907 if (ConstructorRParen.isInvalid()) {
908 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000909 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000910 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000911 }
912
Sebastian Redlf53597f2009-03-15 17:47:39 +0000913 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
914 move_arg(PlacementArgs), PlacementRParen,
915 ParenTypeId, DeclaratorInfo, ConstructorLParen,
916 move_arg(ConstructorArgs), ConstructorRParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000917}
918
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000919/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
920/// passed to ParseDeclaratorInternal.
921///
922/// direct-new-declarator:
923/// '[' expression ']'
924/// direct-new-declarator '[' constant-expression ']'
925///
Chris Lattner59232d32009-01-04 21:25:24 +0000926void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000927 // Parse the array dimensions.
928 bool first = true;
929 while (Tok.is(tok::l_square)) {
930 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000931 OwningExprResult Size(first ? ParseExpression()
932 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000933 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000934 // Recover
935 SkipUntil(tok::r_square);
936 return;
937 }
938 first = false;
939
Sebastian Redlab197ba2009-02-09 18:23:29 +0000940 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000941 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redlab197ba2009-02-09 18:23:29 +0000942 Size.release(), LLoc),
943 RLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000944
Sebastian Redlab197ba2009-02-09 18:23:29 +0000945 if (RLoc.isInvalid())
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000946 return;
947 }
948}
949
950/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
951/// This ambiguity appears in the syntax of the C++ new operator.
952///
953/// new-expression:
954/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
955/// new-initializer[opt]
956///
957/// new-placement:
958/// '(' expression-list ')'
959///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000960bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +0000961 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000962 // The '(' was already consumed.
963 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000964 ParseSpecifierQualifierList(D.getMutableDeclSpec());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000965 D.SetSourceRange(D.getDeclSpec().getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000966 ParseDeclarator(D);
Chris Lattnereaaebc72009-04-25 08:06:05 +0000967 return D.isInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000968 }
969
970 // It's not a type, it has to be an expression list.
971 // Discard the comma locations - ActOnCXXNew has enough parameters.
972 CommaLocsTy CommaLocs;
973 return ParseExpressionList(PlacementArgs, CommaLocs);
974}
975
976/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
977/// to free memory allocated by new.
978///
Chris Lattner59232d32009-01-04 21:25:24 +0000979/// This method is called to parse the 'delete' expression after the optional
980/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
981/// and "Start" is its location. Otherwise, "Start" is the location of the
982/// 'delete' token.
983///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000984/// delete-expression:
985/// '::'[opt] 'delete' cast-expression
986/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +0000987Parser::OwningExprResult
988Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
989 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
990 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000991
992 // Array delete?
993 bool ArrayDelete = false;
994 if (Tok.is(tok::l_square)) {
995 ArrayDelete = true;
996 SourceLocation LHS = ConsumeBracket();
997 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
998 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000999 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001000 }
1001
Sebastian Redl2f7ece72008-12-11 21:36:32 +00001002 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +00001003 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +00001004 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001005
Sebastian Redlf53597f2009-03-15 17:47:39 +00001006 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001007}
Sebastian Redl64b45f72009-01-05 20:52:13 +00001008
1009static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
1010{
1011 switch(kind) {
1012 default: assert(false && "Not a known unary type trait.");
1013 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
1014 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
1015 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
1016 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
1017 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
1018 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
1019 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
1020 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
1021 case tok::kw___is_abstract: return UTT_IsAbstract;
1022 case tok::kw___is_class: return UTT_IsClass;
1023 case tok::kw___is_empty: return UTT_IsEmpty;
1024 case tok::kw___is_enum: return UTT_IsEnum;
1025 case tok::kw___is_pod: return UTT_IsPOD;
1026 case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
1027 case tok::kw___is_union: return UTT_IsUnion;
1028 }
1029}
1030
1031/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
1032/// pseudo-functions that allow implementation of the TR1/C++0x type traits
1033/// templates.
1034///
1035/// primary-expression:
1036/// [GNU] unary-type-trait '(' type-id ')'
1037///
1038Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
1039{
1040 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
1041 SourceLocation Loc = ConsumeToken();
1042
1043 SourceLocation LParen = Tok.getLocation();
1044 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1045 return ExprError();
1046
1047 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
1048 // there will be cryptic errors about mismatched parentheses and missing
1049 // specifiers.
Douglas Gregor809070a2009-02-18 17:45:20 +00001050 TypeResult Ty = ParseTypeName();
Sebastian Redl64b45f72009-01-05 20:52:13 +00001051
1052 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
1053
Douglas Gregor809070a2009-02-18 17:45:20 +00001054 if (Ty.isInvalid())
1055 return ExprError();
1056
1057 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
Sebastian Redl64b45f72009-01-05 20:52:13 +00001058}
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001059
1060/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
1061/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
1062/// based on the context past the parens.
1063Parser::OwningExprResult
1064Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
1065 TypeTy *&CastTy,
1066 SourceLocation LParenLoc,
1067 SourceLocation &RParenLoc) {
1068 assert(getLang().CPlusPlus && "Should only be called for C++!");
1069 assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
1070 assert(isTypeIdInParens() && "Not a type-id!");
1071
1072 OwningExprResult Result(Actions, true);
1073 CastTy = 0;
1074
1075 // We need to disambiguate a very ugly part of the C++ syntax:
1076 //
1077 // (T())x; - type-id
1078 // (T())*x; - type-id
1079 // (T())/x; - expression
1080 // (T()); - expression
1081 //
1082 // The bad news is that we cannot use the specialized tentative parser, since
1083 // it can only verify that the thing inside the parens can be parsed as
1084 // type-id, it is not useful for determining the context past the parens.
1085 //
1086 // The good news is that the parser can disambiguate this part without
Argyrios Kyrtzidisa558a892009-05-22 15:12:46 +00001087 // making any unnecessary Action calls.
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001088 //
1089 // It uses a scheme similar to parsing inline methods. The parenthesized
1090 // tokens are cached, the context that follows is determined (possibly by
1091 // parsing a cast-expression), and then we re-introduce the cached tokens
1092 // into the token stream and parse them appropriately.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001093
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001094 ParenParseOption ParseAs;
1095 CachedTokens Toks;
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001096
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001097 // Store the tokens of the parentheses. We will parse them after we determine
1098 // the context that follows them.
1099 if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
1100 // We didn't find the ')' we expected.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001101 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1102 return ExprError();
1103 }
1104
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001105 if (Tok.is(tok::l_brace)) {
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001106 ParseAs = CompoundLiteral;
1107 } else {
1108 bool NotCastExpr;
Eli Friedmanb53f08a2009-05-25 19:41:42 +00001109 // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
1110 if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
1111 NotCastExpr = true;
1112 } else {
1113 // Try parsing the cast-expression that may follow.
1114 // If it is not a cast-expression, NotCastExpr will be true and no token
1115 // will be consumed.
1116 Result = ParseCastExpression(false/*isUnaryExpression*/,
1117 false/*isAddressofOperand*/,
1118 NotCastExpr);
1119 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001120
1121 // If we parsed a cast-expression, it's really a type-id, otherwise it's
1122 // an expression.
1123 ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001124 }
1125
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001126 // The current token should go after the cached tokens.
1127 Toks.push_back(Tok);
1128 // Re-enter the stored parenthesized tokens into the token stream, so we may
1129 // parse them now.
1130 PP.EnterTokenStream(Toks.data(), Toks.size(),
1131 true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
1132 // Drop the current token and bring the first cached one. It's the same token
1133 // as when we entered this function.
1134 ConsumeAnyToken();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001135
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001136 if (ParseAs >= CompoundLiteral) {
1137 TypeResult Ty = ParseTypeName();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001138
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001139 // Match the ')'.
1140 if (Tok.is(tok::r_paren))
1141 RParenLoc = ConsumeParen();
1142 else
1143 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001144
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001145 if (ParseAs == CompoundLiteral) {
1146 ExprType = CompoundLiteral;
1147 return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
1148 }
1149
1150 // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
1151 assert(ParseAs == CastExpr);
1152
1153 if (Ty.isInvalid())
1154 return ExprError();
1155
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001156 CastTy = Ty.get();
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001157
1158 // Result is what ParseCastExpression returned earlier.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001159 if (!Result.isInvalid())
1160 Result = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc,move(Result));
1161 return move(Result);
1162 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001163
1164 // Not a compound literal, and not followed by a cast-expression.
1165 assert(ParseAs == SimpleExpr);
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001166
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001167 ExprType = SimpleExpr;
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001168 Result = ParseExpression();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001169 if (!Result.isInvalid() && Tok.is(tok::r_paren))
1170 Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
1171
1172 // Match the ')'.
1173 if (Result.isInvalid()) {
1174 SkipUntil(tok::r_paren);
1175 return ExprError();
1176 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001177
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001178 if (Tok.is(tok::r_paren))
1179 RParenLoc = ConsumeParen();
1180 else
1181 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1182
1183 return move(Result);
1184}