blob: f00edddffe5ce2fcf8fc2c7d775045ea817d8aaa [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"
Sebastian Redla55e52c2008-11-25 22:21:31 +000017#include "AstGuard.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000018using namespace clang;
19
Chris Lattner7a0ab5f2009-01-06 06:59:53 +000020/// 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.
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000024///
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///
Chris Lattner7a0ab5f2009-01-06 06:59:53 +000034bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000035 assert(getLang().CPlusPlus &&
Chris Lattner7452c6f2009-01-05 01:24:05 +000036 "Call sites of this function should be guarded by checking for C++");
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000037
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000038 if (Tok.is(tok::annot_cxxscope)) {
Douglas Gregor35073692009-03-26 23:56:24 +000039 SS.setScopeRep(Tok.getAnnotationValue());
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000040 SS.setRange(Tok.getAnnotationRange());
41 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000042 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000043 }
Chris Lattnere607e802009-01-04 21:14:15 +000044
Douglas Gregor39a8de12009-02-25 19:37:18 +000045 bool HasScopeSpecifier = false;
46
Chris Lattner5b454732009-01-05 03:55:46 +000047 if (Tok.is(tok::coloncolon)) {
48 // ::new and ::delete aren't nested-name-specifiers.
49 tok::TokenKind NextKind = NextToken().getKind();
50 if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
51 return false;
Chris Lattner55a7cef2009-01-05 00:13:00 +000052
Chris Lattner55a7cef2009-01-05 00:13:00 +000053 // '::' - Global scope qualifier.
Chris Lattner357089d2009-01-05 02:07:19 +000054 SourceLocation CCLoc = ConsumeToken();
Chris Lattner357089d2009-01-05 02:07:19 +000055 SS.setBeginLoc(CCLoc);
Douglas Gregor35073692009-03-26 23:56:24 +000056 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
Chris Lattner357089d2009-01-05 02:07:19 +000057 SS.setEndLoc(CCLoc);
Douglas Gregor39a8de12009-02-25 19:37:18 +000058 HasScopeSpecifier = true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000059 }
60
Douglas Gregor39a8de12009-02-25 19:37:18 +000061 while (true) {
62 // nested-name-specifier:
63 // type-name '::'
64 // namespace-name '::'
65 // nested-name-specifier identifier '::'
66 if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
67 // We have an identifier followed by a '::'. Lookup this name
68 // as the name in a nested-name-specifier.
69 IdentifierInfo *II = Tok.getIdentifierInfo();
70 SourceLocation IdLoc = ConsumeToken();
71 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
72 SourceLocation CCLoc = ConsumeToken();
73
74 if (!HasScopeSpecifier) {
75 SS.setBeginLoc(IdLoc);
76 HasScopeSpecifier = true;
77 }
78
79 if (SS.isInvalid())
80 continue;
81
Douglas Gregor35073692009-03-26 23:56:24 +000082 SS.setScopeRep(
Douglas Gregor39a8de12009-02-25 19:37:18 +000083 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
84 SS.setEndLoc(CCLoc);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000085 continue;
Douglas Gregor39a8de12009-02-25 19:37:18 +000086 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000087
Douglas Gregor39a8de12009-02-25 19:37:18 +000088 // nested-name-specifier:
89 // type-name '::'
90 // nested-name-specifier 'template'[opt] simple-template-id '::'
91 if ((Tok.is(tok::identifier) && NextToken().is(tok::less)) ||
92 Tok.is(tok::kw_template)) {
93 // Parse the optional 'template' keyword, then make sure we have
94 // 'identifier <' after it.
Douglas Gregor39a8de12009-02-25 19:37:18 +000095 if (Tok.is(tok::kw_template)) {
Douglas Gregorc45c2322009-03-31 00:43:58 +000096 SourceLocation TemplateKWLoc = ConsumeToken();
Douglas Gregor39a8de12009-02-25 19:37:18 +000097
98 if (Tok.isNot(tok::identifier)) {
99 Diag(Tok.getLocation(),
100 diag::err_id_after_template_in_nested_name_spec)
101 << SourceRange(TemplateKWLoc);
102 break;
103 }
104
105 if (NextToken().isNot(tok::less)) {
106 Diag(NextToken().getLocation(),
107 diag::err_less_after_template_name_in_nested_name_spec)
108 << Tok.getIdentifierInfo()->getName()
109 << SourceRange(TemplateKWLoc, Tok.getLocation());
110 break;
111 }
Douglas Gregorc45c2322009-03-31 00:43:58 +0000112
113 TemplateTy Template
114 = Actions.ActOnDependentTemplateName(TemplateKWLoc,
115 *Tok.getIdentifierInfo(),
116 Tok.getLocation(),
117 SS);
118 AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
119 &SS, TemplateKWLoc, false);
120 continue;
Douglas Gregor39a8de12009-02-25 19:37:18 +0000121 }
122
Douglas Gregor7532dc62009-03-30 22:58:21 +0000123 TemplateTy Template;
Douglas Gregorc45c2322009-03-31 00:43:58 +0000124 TemplateNameKind TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(),
125 CurScope, Template, &SS);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000126 if (TNK) {
127 // We have found a template name, so annotate this this token
128 // with a template-id annotation. We do not permit the
129 // template-id to be translated into a type annotation,
130 // because some clients (e.g., the parsing of class template
131 // specializations) still want to see the original template-id
132 // token.
Douglas Gregorc45c2322009-03-31 00:43:58 +0000133 AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), false);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000134 continue;
135 }
136 }
137
138 if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
139 // We have
140 //
141 // simple-template-id '::'
142 //
143 // So we need to check whether the simple-template-id is of the
Douglas Gregorc45c2322009-03-31 00:43:58 +0000144 // right kind (it should name a type or be dependent), and then
145 // convert it into a type within the nested-name-specifier.
Douglas Gregor39a8de12009-02-25 19:37:18 +0000146 TemplateIdAnnotation *TemplateId
147 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
148
Douglas Gregorc45c2322009-03-31 00:43:58 +0000149 if (TemplateId->Kind == TNK_Type_template ||
150 TemplateId->Kind == TNK_Dependent_template_name) {
Douglas Gregor31a19b62009-04-01 21:51:26 +0000151 AnnotateTemplateIdTokenAsType(&SS);
152 SS.clear();
Douglas Gregor39a8de12009-02-25 19:37:18 +0000153
154 assert(Tok.is(tok::annot_typename) &&
155 "AnnotateTemplateIdTokenAsType isn't working");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000156 Token TypeToken = Tok;
157 ConsumeToken();
158 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
159 SourceLocation CCLoc = ConsumeToken();
160
161 if (!HasScopeSpecifier) {
162 SS.setBeginLoc(TypeToken.getLocation());
163 HasScopeSpecifier = true;
164 }
Douglas Gregor31a19b62009-04-01 21:51:26 +0000165
166 if (TypeToken.getAnnotationValue())
167 SS.setScopeRep(
168 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
169 TypeToken.getAnnotationValue(),
170 TypeToken.getAnnotationRange(),
171 CCLoc));
172 else
173 SS.setScopeRep(0);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000174 SS.setEndLoc(CCLoc);
175 continue;
176 } else
Douglas Gregorc45c2322009-03-31 00:43:58 +0000177 assert(false && "FIXME: Only type template names supported here");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000178 }
179
180 // We don't have any tokens that form the beginning of a
181 // nested-name-specifier, so we're done.
182 break;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000183 }
Douglas Gregor39a8de12009-02-25 19:37:18 +0000184
185 return HasScopeSpecifier;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000186}
187
188/// ParseCXXIdExpression - Handle id-expression.
189///
190/// id-expression:
191/// unqualified-id
192/// qualified-id
193///
194/// unqualified-id:
195/// identifier
196/// operator-function-id
197/// conversion-function-id [TODO]
198/// '~' class-name [TODO]
199/// template-id [TODO]
200///
201/// qualified-id:
202/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
203/// '::' identifier
204/// '::' operator-function-id
205/// '::' template-id [TODO]
206///
207/// nested-name-specifier:
208/// type-name '::'
209/// namespace-name '::'
210/// nested-name-specifier identifier '::'
211/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
212///
213/// NOTE: The standard specifies that, for qualified-id, the parser does not
214/// expect:
215///
216/// '::' conversion-function-id
217/// '::' '~' class-name
218///
219/// This may cause a slight inconsistency on diagnostics:
220///
221/// class C {};
222/// namespace A {}
223/// void f() {
224/// :: A :: ~ C(); // Some Sema error about using destructor with a
225/// // namespace.
226/// :: ~ C(); // Some Parser error like 'unexpected ~'.
227/// }
228///
229/// We simplify the parser a bit and make it work like:
230///
231/// qualified-id:
232/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
233/// '::' unqualified-id
234///
235/// That way Sema can handle and report similar errors for namespaces and the
236/// global scope.
237///
Sebastian Redlebc07d52009-02-03 20:19:35 +0000238/// The isAddressOfOperand parameter indicates that this id-expression is a
239/// direct operand of the address-of operator. This is, besides member contexts,
240/// the only place where a qualified-id naming a non-static class member may
241/// appear.
242///
243Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000244 // qualified-id:
245 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
246 // '::' unqualified-id
247 //
248 CXXScopeSpec SS;
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000249 ParseOptionalCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000250
251 // unqualified-id:
252 // identifier
253 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000254 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000255 // '~' class-name [TODO]
256 // template-id [TODO]
257 //
258 switch (Tok.getKind()) {
259 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000260 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000261
262 case tok::identifier: {
263 // Consume the identifier so that we can see if it is followed by a '('.
264 IdentifierInfo &II = *Tok.getIdentifierInfo();
265 SourceLocation L = ConsumeToken();
Sebastian Redlebc07d52009-02-03 20:19:35 +0000266 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
267 &SS, isAddressOfOperand);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000268 }
269
270 case tok::kw_operator: {
271 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000272 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000273 return Actions.ActOnCXXOperatorFunctionIdExpr(
Sebastian Redlebc07d52009-02-03 20:19:35 +0000274 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
275 isAddressOfOperand);
Chris Lattner7452c6f2009-01-05 01:24:05 +0000276 if (TypeTy *Type = ParseConversionFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000277 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
Sebastian Redlebc07d52009-02-03 20:19:35 +0000278 Tok.is(tok::l_paren), SS,
279 isAddressOfOperand);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000280
Douglas Gregor2def4832008-11-17 20:34:05 +0000281 // We already complained about a bad conversion-function-id,
282 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000283 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000284 }
285
286 } // switch.
287
288 assert(0 && "The switch was supposed to take care everything.");
289}
290
Reid Spencer5f016e22007-07-11 17:01:13 +0000291/// ParseCXXCasts - This handles the various ways to cast expressions to another
292/// type.
293///
294/// postfix-expression: [C++ 5.2p1]
295/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
296/// 'static_cast' '<' type-name '>' '(' expression ')'
297/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
298/// 'const_cast' '<' type-name '>' '(' expression ')'
299///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000300Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000301 tok::TokenKind Kind = Tok.getKind();
302 const char *CastName = 0; // For error messages
303
304 switch (Kind) {
305 default: assert(0 && "Unknown C++ cast!"); abort();
306 case tok::kw_const_cast: CastName = "const_cast"; break;
307 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
308 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
309 case tok::kw_static_cast: CastName = "static_cast"; break;
310 }
311
312 SourceLocation OpLoc = ConsumeToken();
313 SourceLocation LAngleBracketLoc = Tok.getLocation();
314
315 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000316 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000317
Douglas Gregor809070a2009-02-18 17:45:20 +0000318 TypeResult CastTy = ParseTypeName();
Reid Spencer5f016e22007-07-11 17:01:13 +0000319 SourceLocation RAngleBracketLoc = Tok.getLocation();
320
Chris Lattner1ab3b962008-11-18 07:48:38 +0000321 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000322 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000323
324 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
325
Chris Lattner1ab3b962008-11-18 07:48:38 +0000326 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000327 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000328
Sebastian Redld8c4e152008-12-11 22:33:27 +0000329 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000330
Douglas Gregor809070a2009-02-18 17:45:20 +0000331 if (!Result.isInvalid() && !CastTy.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000332 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000333 LAngleBracketLoc, CastTy.get(),
Douglas Gregor809070a2009-02-18 17:45:20 +0000334 RAngleBracketLoc,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000335 LParenLoc, move(Result), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000336
Sebastian Redl20df9b72008-12-11 22:51:44 +0000337 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000338}
339
Sebastian Redlc42e1182008-11-11 11:37:55 +0000340/// ParseCXXTypeid - This handles the C++ typeid expression.
341///
342/// postfix-expression: [C++ 5.2p1]
343/// 'typeid' '(' expression ')'
344/// 'typeid' '(' type-id ')'
345///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000346Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000347 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
348
349 SourceLocation OpLoc = ConsumeToken();
350 SourceLocation LParenLoc = Tok.getLocation();
351 SourceLocation RParenLoc;
352
353 // typeid expressions are always parenthesized.
354 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
355 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000356 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000357
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000358 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000359
360 if (isTypeIdInParens()) {
Douglas Gregor809070a2009-02-18 17:45:20 +0000361 TypeResult Ty = ParseTypeName();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000362
363 // Match the ')'.
364 MatchRHSPunctuation(tok::r_paren, LParenLoc);
365
Douglas Gregor809070a2009-02-18 17:45:20 +0000366 if (Ty.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000367 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000368
369 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Douglas Gregor809070a2009-02-18 17:45:20 +0000370 Ty.get(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000371 } else {
372 Result = ParseExpression();
373
374 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000375 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000376 SkipUntil(tok::r_paren);
377 else {
378 MatchRHSPunctuation(tok::r_paren, LParenLoc);
379
380 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000381 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000382 }
383 }
384
Sebastian Redl20df9b72008-12-11 22:51:44 +0000385 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000386}
387
Reid Spencer5f016e22007-07-11 17:01:13 +0000388/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
389///
390/// boolean-literal: [C++ 2.13.5]
391/// 'true'
392/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000393Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000394 tok::TokenKind Kind = Tok.getKind();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000395 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Reid Spencer5f016e22007-07-11 17:01:13 +0000396}
Chris Lattner50dd2892008-02-26 00:51:44 +0000397
398/// ParseThrowExpression - This handles the C++ throw expression.
399///
400/// throw-expression: [C++ 15]
401/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000402Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000403 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000404 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000405
Chris Lattner2a2819a2008-04-06 06:02:23 +0000406 // If the current token isn't the start of an assignment-expression,
407 // then the expression is not present. This handles things like:
408 // "C ? throw : (void)42", which is crazy but legal.
409 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
410 case tok::semi:
411 case tok::r_paren:
412 case tok::r_square:
413 case tok::r_brace:
414 case tok::colon:
415 case tok::comma:
Sebastian Redlf53597f2009-03-15 17:47:39 +0000416 return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
Chris Lattner50dd2892008-02-26 00:51:44 +0000417
Chris Lattner2a2819a2008-04-06 06:02:23 +0000418 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000419 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000420 if (Expr.isInvalid()) return move(Expr);
Sebastian Redlf53597f2009-03-15 17:47:39 +0000421 return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000422 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000423}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000424
425/// ParseCXXThis - This handles the C++ 'this' pointer.
426///
427/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
428/// a non-lvalue expression whose value is the address of the object for which
429/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000430Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000431 assert(Tok.is(tok::kw_this) && "Not 'this'!");
432 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000433 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000434}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000435
436/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
437/// Can be interpreted either as function-style casting ("int(x)")
438/// or class type construction ("ClassType(x,y,z)")
439/// or creation of a value-initialized type ("int()").
440///
441/// postfix-expression: [C++ 5.2p1]
442/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
443/// typename-specifier '(' expression-list[opt] ')' [TODO]
444///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000445Parser::OwningExprResult
446Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000447 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000448 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000449
450 assert(Tok.is(tok::l_paren) && "Expected '('!");
451 SourceLocation LParenLoc = ConsumeParen();
452
Sebastian Redla55e52c2008-11-25 22:21:31 +0000453 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000454 CommaLocsTy CommaLocs;
455
456 if (Tok.isNot(tok::r_paren)) {
457 if (ParseExpressionList(Exprs, CommaLocs)) {
458 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000459 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000460 }
461 }
462
463 // Match the ')'.
464 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
465
466 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
467 "Unexpected number of commas!");
Sebastian Redlf53597f2009-03-15 17:47:39 +0000468 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
469 LParenLoc, move_arg(Exprs),
470 &CommaLocs[0], RParenLoc);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000471}
472
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000473/// ParseCXXCondition - if/switch/while/for condition expression.
474///
475/// condition:
476/// expression
477/// type-specifier-seq declarator '=' assignment-expression
478/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
479/// '=' assignment-expression
480///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000481Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000482 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000483 return ParseExpression(); // expression
484
485 SourceLocation StartLoc = Tok.getLocation();
486
487 // type-specifier-seq
488 DeclSpec DS;
489 ParseSpecifierQualifierList(DS);
490
491 // declarator
492 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
493 ParseDeclarator(DeclaratorInfo);
494
495 // simple-asm-expr[opt]
496 if (Tok.is(tok::kw_asm)) {
Sebastian Redlab197ba2009-02-09 18:23:29 +0000497 SourceLocation Loc;
498 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000499 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000500 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000501 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000502 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000503 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000504 DeclaratorInfo.SetRangeEnd(Loc);
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000505 }
506
507 // If attributes are present, parse them.
Sebastian Redlab197ba2009-02-09 18:23:29 +0000508 if (Tok.is(tok::kw___attribute)) {
509 SourceLocation Loc;
510 AttributeList *AttrList = ParseAttributes(&Loc);
511 DeclaratorInfo.AddAttributes(AttrList, Loc);
512 }
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000513
514 // '=' assignment-expression
515 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000516 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000517 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000518 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000519 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000520 return ExprError();
521
Sebastian Redlf53597f2009-03-15 17:47:39 +0000522 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
523 DeclaratorInfo,EqualLoc,
524 move(AssignExpr));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000525}
526
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000527/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
528/// This should only be called when the current token is known to be part of
529/// simple-type-specifier.
530///
531/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000532/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000533/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
534/// char
535/// wchar_t
536/// bool
537/// short
538/// int
539/// long
540/// signed
541/// unsigned
542/// float
543/// double
544/// void
545/// [GNU] typeof-specifier
546/// [C++0x] auto [TODO]
547///
548/// type-name:
549/// class-name
550/// enum-name
551/// typedef-name
552///
553void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
554 DS.SetRangeStart(Tok.getLocation());
555 const char *PrevSpec;
556 SourceLocation Loc = Tok.getLocation();
557
558 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000559 case tok::identifier: // foo::bar
560 case tok::coloncolon: // ::foo::bar
561 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000562 default:
563 assert(0 && "Not a simple-type-specifier token!");
564 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000565
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000566 // type-name
Chris Lattnerb31757b2009-01-06 05:06:21 +0000567 case tok::annot_typename: {
Douglas Gregor1a51b4a2009-02-09 15:09:02 +0000568 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000569 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000570 break;
571 }
572
573 // builtin types
574 case tok::kw_short:
575 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
576 break;
577 case tok::kw_long:
578 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
579 break;
580 case tok::kw_signed:
581 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
582 break;
583 case tok::kw_unsigned:
584 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
585 break;
586 case tok::kw_void:
587 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
588 break;
589 case tok::kw_char:
590 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
591 break;
592 case tok::kw_int:
593 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
594 break;
595 case tok::kw_float:
596 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
597 break;
598 case tok::kw_double:
599 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
600 break;
601 case tok::kw_wchar_t:
602 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
603 break;
604 case tok::kw_bool:
605 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
606 break;
607
608 // GNU typeof support.
609 case tok::kw_typeof:
610 ParseTypeofSpecifier(DS);
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000611 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000612 return;
613 }
Chris Lattnerb31757b2009-01-06 05:06:21 +0000614 if (Tok.is(tok::annot_typename))
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000615 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
616 else
617 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000618 ConsumeToken();
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000619 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000620}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000621
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000622/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
623/// [dcl.name]), which is a non-empty sequence of type-specifiers,
624/// e.g., "const short int". Note that the DeclSpec is *not* finished
625/// by parsing the type-specifier-seq, because these sequences are
626/// typically followed by some form of declarator. Returns true and
627/// emits diagnostics if this is not a type-specifier-seq, false
628/// otherwise.
629///
630/// type-specifier-seq: [C++ 8.1]
631/// type-specifier type-specifier-seq[opt]
632///
633bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
634 DS.SetRangeStart(Tok.getLocation());
635 const char *PrevSpec = 0;
636 int isInvalid = 0;
637
638 // Parse one or more of the type specifiers.
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000639 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000640 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000641 return true;
642 }
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000643
Ted Kremenekb8006e52009-01-06 19:17:58 +0000644 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000645
646 return false;
647}
648
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000649/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000650/// operator name (C++ [over.oper]). If successful, returns the
651/// predefined identifier that corresponds to that overloaded
652/// operator. Otherwise, returns NULL and does not consume any tokens.
653///
654/// operator-function-id: [C++ 13.5]
655/// 'operator' operator
656///
657/// operator: one of
658/// new delete new[] delete[]
659/// + - * / % ^ & | ~
660/// ! = < > += -= *= /= %=
661/// ^= &= |= << >> >>= <<= == !=
662/// <= >= && || ++ -- , ->* ->
663/// () []
Sebastian Redlab197ba2009-02-09 18:23:29 +0000664OverloadedOperatorKind
665Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000666 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Sebastian Redlab197ba2009-02-09 18:23:29 +0000667 SourceLocation Loc;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000668
669 OverloadedOperatorKind Op = OO_None;
670 switch (NextToken().getKind()) {
671 case tok::kw_new:
672 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000673 Loc = ConsumeToken(); // 'new'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000674 if (Tok.is(tok::l_square)) {
675 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000676 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000677 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
678 Op = OO_Array_New;
679 } else {
680 Op = OO_New;
681 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000682 if (EndLoc)
683 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000684 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000685
686 case tok::kw_delete:
687 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000688 Loc = ConsumeToken(); // 'delete'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000689 if (Tok.is(tok::l_square)) {
690 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000691 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000692 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
693 Op = OO_Array_Delete;
694 } else {
695 Op = OO_Delete;
696 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000697 if (EndLoc)
698 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000699 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000700
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000701#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000702 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000703#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000704#include "clang/Basic/OperatorKinds.def"
705
706 case tok::l_paren:
707 ConsumeToken(); // 'operator'
708 ConsumeParen(); // '('
Sebastian Redlab197ba2009-02-09 18:23:29 +0000709 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000710 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000711 if (EndLoc)
712 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000713 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000714
715 case tok::l_square:
716 ConsumeToken(); // 'operator'
717 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000718 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000719 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000720 if (EndLoc)
721 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000722 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000723
724 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000725 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000726 }
727
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000728 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000729 Loc = ConsumeAnyToken(); // the operator itself
730 if (EndLoc)
731 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000732 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000733}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000734
735/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
736/// which expresses the name of a user-defined conversion operator
737/// (C++ [class.conv.fct]p1). Returns the type that this operator is
738/// specifying a conversion for, or NULL if there was an error.
739///
740/// conversion-function-id: [C++ 12.3.2]
741/// operator conversion-type-id
742///
743/// conversion-type-id:
744/// type-specifier-seq conversion-declarator[opt]
745///
746/// conversion-declarator:
747/// ptr-operator conversion-declarator[opt]
Sebastian Redlab197ba2009-02-09 18:23:29 +0000748Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000749 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
750 ConsumeToken(); // 'operator'
751
752 // Parse the type-specifier-seq.
753 DeclSpec DS;
754 if (ParseCXXTypeSpecifierSeq(DS))
755 return 0;
756
757 // Parse the conversion-declarator, which is merely a sequence of
758 // ptr-operators.
759 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000760 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000761 if (EndLoc)
762 *EndLoc = D.getSourceRange().getEnd();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000763
764 // Finish up the type.
765 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000766 if (Result.isInvalid())
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000767 return 0;
768 else
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000769 return Result.get();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000770}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000771
772/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
773/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000774///
775/// This method is called to parse the new expression after the optional :: has
776/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
777/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000778///
779/// new-expression:
780/// '::'[opt] 'new' new-placement[opt] new-type-id
781/// new-initializer[opt]
782/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
783/// new-initializer[opt]
784///
785/// new-placement:
786/// '(' expression-list ')'
787///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000788/// new-type-id:
789/// type-specifier-seq new-declarator[opt]
790///
791/// new-declarator:
792/// ptr-operator new-declarator[opt]
793/// direct-new-declarator
794///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000795/// new-initializer:
796/// '(' expression-list[opt] ')'
797/// [C++0x] braced-init-list [TODO]
798///
Chris Lattner59232d32009-01-04 21:25:24 +0000799Parser::OwningExprResult
800Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
801 assert(Tok.is(tok::kw_new) && "expected 'new' token");
802 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000803
804 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
805 // second form of new-expression. It can't be a new-type-id.
806
Sebastian Redla55e52c2008-11-25 22:21:31 +0000807 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000808 SourceLocation PlacementLParen, PlacementRParen;
809
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000810 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000811 DeclSpec DS;
812 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000813 if (Tok.is(tok::l_paren)) {
814 // If it turns out to be a placement, we change the type location.
815 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000816 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
817 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000818 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000819 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000820
821 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000822 if (PlacementRParen.isInvalid()) {
823 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000824 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000825 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000826
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000827 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000828 // Reset the placement locations. There was no placement.
829 PlacementLParen = PlacementRParen = SourceLocation();
830 ParenTypeId = true;
831 } else {
832 // We still need the type.
833 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000834 SourceLocation LParen = ConsumeParen();
835 ParseSpecifierQualifierList(DS);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000836 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000837 ParseDeclarator(DeclaratorInfo);
838 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000839 ParenTypeId = true;
840 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000841 if (ParseCXXTypeSpecifierSeq(DS))
842 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000843 else {
844 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000845 ParseDeclaratorInternal(DeclaratorInfo,
846 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000847 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000848 ParenTypeId = false;
849 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000850 }
851 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000852 // A new-type-id is a simplified type-id, where essentially the
853 // direct-declarator is replaced by a direct-new-declarator.
854 if (ParseCXXTypeSpecifierSeq(DS))
855 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000856 else {
857 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000858 ParseDeclaratorInternal(DeclaratorInfo,
859 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000860 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000861 ParenTypeId = false;
862 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000863 if (DeclaratorInfo.getInvalidType()) {
864 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000865 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000866 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000867
Sebastian Redla55e52c2008-11-25 22:21:31 +0000868 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000869 SourceLocation ConstructorLParen, ConstructorRParen;
870
871 if (Tok.is(tok::l_paren)) {
872 ConstructorLParen = ConsumeParen();
873 if (Tok.isNot(tok::r_paren)) {
874 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000875 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
876 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000877 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000878 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000879 }
880 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000881 if (ConstructorRParen.isInvalid()) {
882 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000883 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000884 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000885 }
886
Sebastian Redlf53597f2009-03-15 17:47:39 +0000887 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
888 move_arg(PlacementArgs), PlacementRParen,
889 ParenTypeId, DeclaratorInfo, ConstructorLParen,
890 move_arg(ConstructorArgs), ConstructorRParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000891}
892
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000893/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
894/// passed to ParseDeclaratorInternal.
895///
896/// direct-new-declarator:
897/// '[' expression ']'
898/// direct-new-declarator '[' constant-expression ']'
899///
Chris Lattner59232d32009-01-04 21:25:24 +0000900void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000901 // Parse the array dimensions.
902 bool first = true;
903 while (Tok.is(tok::l_square)) {
904 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000905 OwningExprResult Size(first ? ParseExpression()
906 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000907 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000908 // Recover
909 SkipUntil(tok::r_square);
910 return;
911 }
912 first = false;
913
Sebastian Redlab197ba2009-02-09 18:23:29 +0000914 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000915 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redlab197ba2009-02-09 18:23:29 +0000916 Size.release(), LLoc),
917 RLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000918
Sebastian Redlab197ba2009-02-09 18:23:29 +0000919 if (RLoc.isInvalid())
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000920 return;
921 }
922}
923
924/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
925/// This ambiguity appears in the syntax of the C++ new operator.
926///
927/// new-expression:
928/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
929/// new-initializer[opt]
930///
931/// new-placement:
932/// '(' expression-list ')'
933///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000934bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +0000935 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000936 // The '(' was already consumed.
937 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000938 ParseSpecifierQualifierList(D.getMutableDeclSpec());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000939 D.SetSourceRange(D.getDeclSpec().getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000940 ParseDeclarator(D);
941 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000942 }
943
944 // It's not a type, it has to be an expression list.
945 // Discard the comma locations - ActOnCXXNew has enough parameters.
946 CommaLocsTy CommaLocs;
947 return ParseExpressionList(PlacementArgs, CommaLocs);
948}
949
950/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
951/// to free memory allocated by new.
952///
Chris Lattner59232d32009-01-04 21:25:24 +0000953/// This method is called to parse the 'delete' expression after the optional
954/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
955/// and "Start" is its location. Otherwise, "Start" is the location of the
956/// 'delete' token.
957///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000958/// delete-expression:
959/// '::'[opt] 'delete' cast-expression
960/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +0000961Parser::OwningExprResult
962Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
963 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
964 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000965
966 // Array delete?
967 bool ArrayDelete = false;
968 if (Tok.is(tok::l_square)) {
969 ArrayDelete = true;
970 SourceLocation LHS = ConsumeBracket();
971 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
972 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000973 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000974 }
975
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000976 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000977 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000978 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000979
Sebastian Redlf53597f2009-03-15 17:47:39 +0000980 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000981}
Sebastian Redl64b45f72009-01-05 20:52:13 +0000982
983static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
984{
985 switch(kind) {
986 default: assert(false && "Not a known unary type trait.");
987 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
988 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
989 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
990 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
991 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
992 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
993 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
994 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
995 case tok::kw___is_abstract: return UTT_IsAbstract;
996 case tok::kw___is_class: return UTT_IsClass;
997 case tok::kw___is_empty: return UTT_IsEmpty;
998 case tok::kw___is_enum: return UTT_IsEnum;
999 case tok::kw___is_pod: return UTT_IsPOD;
1000 case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
1001 case tok::kw___is_union: return UTT_IsUnion;
1002 }
1003}
1004
1005/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
1006/// pseudo-functions that allow implementation of the TR1/C++0x type traits
1007/// templates.
1008///
1009/// primary-expression:
1010/// [GNU] unary-type-trait '(' type-id ')'
1011///
1012Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
1013{
1014 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
1015 SourceLocation Loc = ConsumeToken();
1016
1017 SourceLocation LParen = Tok.getLocation();
1018 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1019 return ExprError();
1020
1021 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
1022 // there will be cryptic errors about mismatched parentheses and missing
1023 // specifiers.
Douglas Gregor809070a2009-02-18 17:45:20 +00001024 TypeResult Ty = ParseTypeName();
Sebastian Redl64b45f72009-01-05 20:52:13 +00001025
1026 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
1027
Douglas Gregor809070a2009-02-18 17:45:20 +00001028 if (Ty.isInvalid())
1029 return ExprError();
1030
1031 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
Sebastian Redl64b45f72009-01-05 20:52:13 +00001032}