blob: e9cca9fe1d2f941291751cd4e089e2104a1ec2bb [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///
Douglas Gregor495c35d2009-08-25 22:51:20 +000033bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
34 bool EnteringContext) {
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++");
Douglas Gregor495c35d2009-08-25 22:51:20 +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:
Chris Lattner77cf72a2009-06-26 03:47:46 +000063 // nested-name-specifier 'template'[opt] simple-template-id '::'
64
65 // Parse the optional 'template' keyword, then make sure we have
66 // 'identifier <' after it.
67 if (Tok.is(tok::kw_template)) {
Eli Friedmaneab975d2009-08-29 04:08:08 +000068 // If we don't have a scope specifier, this isn't a
69 // nested-name-specifier, since they aren't allowed to start with
70 // 'template'.
71 if (!HasScopeSpecifier)
72 break;
73
Chris Lattner77cf72a2009-06-26 03:47:46 +000074 SourceLocation TemplateKWLoc = ConsumeToken();
75
76 if (Tok.isNot(tok::identifier)) {
77 Diag(Tok.getLocation(),
78 diag::err_id_after_template_in_nested_name_spec)
79 << SourceRange(TemplateKWLoc);
80 break;
81 }
82
83 if (NextToken().isNot(tok::less)) {
84 Diag(NextToken().getLocation(),
85 diag::err_less_after_template_name_in_nested_name_spec)
86 << Tok.getIdentifierInfo()->getName()
87 << SourceRange(TemplateKWLoc, Tok.getLocation());
88 break;
89 }
90
91 TemplateTy Template
92 = Actions.ActOnDependentTemplateName(TemplateKWLoc,
93 *Tok.getIdentifierInfo(),
94 Tok.getLocation(), SS);
Eli Friedmaneab975d2009-08-29 04:08:08 +000095 if (!Template)
96 break;
Chris Lattnerc8e27cc2009-06-26 04:27:47 +000097 if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
98 &SS, TemplateKWLoc, false))
99 break;
100
Chris Lattner77cf72a2009-06-26 03:47:46 +0000101 continue;
102 }
103
Douglas Gregor39a8de12009-02-25 19:37:18 +0000104 if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
105 // We have
106 //
107 // simple-template-id '::'
108 //
109 // So we need to check whether the simple-template-id is of the
Douglas Gregorc45c2322009-03-31 00:43:58 +0000110 // right kind (it should name a type or be dependent), and then
111 // convert it into a type within the nested-name-specifier.
Douglas Gregor39a8de12009-02-25 19:37:18 +0000112 TemplateIdAnnotation *TemplateId
113 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
114
Douglas Gregorc45c2322009-03-31 00:43:58 +0000115 if (TemplateId->Kind == TNK_Type_template ||
116 TemplateId->Kind == TNK_Dependent_template_name) {
Douglas Gregor31a19b62009-04-01 21:51:26 +0000117 AnnotateTemplateIdTokenAsType(&SS);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000118
119 assert(Tok.is(tok::annot_typename) &&
120 "AnnotateTemplateIdTokenAsType isn't working");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000121 Token TypeToken = Tok;
122 ConsumeToken();
123 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
124 SourceLocation CCLoc = ConsumeToken();
125
126 if (!HasScopeSpecifier) {
127 SS.setBeginLoc(TypeToken.getLocation());
128 HasScopeSpecifier = true;
129 }
Douglas Gregor31a19b62009-04-01 21:51:26 +0000130
131 if (TypeToken.getAnnotationValue())
132 SS.setScopeRep(
133 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
134 TypeToken.getAnnotationValue(),
135 TypeToken.getAnnotationRange(),
136 CCLoc));
137 else
138 SS.setScopeRep(0);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000139 SS.setEndLoc(CCLoc);
140 continue;
Chris Lattner67b9e832009-06-26 03:45:46 +0000141 }
142
143 assert(false && "FIXME: Only type template names supported here");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000144 }
145
Chris Lattner5c7f7862009-06-26 03:52:38 +0000146
147 // The rest of the nested-name-specifier possibilities start with
148 // tok::identifier.
149 if (Tok.isNot(tok::identifier))
150 break;
151
152 IdentifierInfo &II = *Tok.getIdentifierInfo();
153
154 // nested-name-specifier:
155 // type-name '::'
156 // namespace-name '::'
157 // nested-name-specifier identifier '::'
158 Token Next = NextToken();
159 if (Next.is(tok::coloncolon)) {
160 // We have an identifier followed by a '::'. Lookup this name
161 // as the name in a nested-name-specifier.
162 SourceLocation IdLoc = ConsumeToken();
163 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
164 SourceLocation CCLoc = ConsumeToken();
165
166 if (!HasScopeSpecifier) {
167 SS.setBeginLoc(IdLoc);
168 HasScopeSpecifier = true;
169 }
170
171 if (SS.isInvalid())
172 continue;
173
174 SS.setScopeRep(
Douglas Gregor495c35d2009-08-25 22:51:20 +0000175 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
176 EnteringContext));
Chris Lattner5c7f7862009-06-26 03:52:38 +0000177 SS.setEndLoc(CCLoc);
178 continue;
179 }
180
181 // nested-name-specifier:
182 // type-name '<'
183 if (Next.is(tok::less)) {
184 TemplateTy Template;
Douglas Gregor495c35d2009-08-25 22:51:20 +0000185 if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope, &SS,
186 EnteringContext,
187 Template)) {
Chris Lattner5c7f7862009-06-26 03:52:38 +0000188 // We have found a template name, so annotate this this token
189 // with a template-id annotation. We do not permit the
190 // template-id to be translated into a type annotation,
191 // because some clients (e.g., the parsing of class template
192 // specializations) still want to see the original template-id
193 // token.
Chris Lattnerc8e27cc2009-06-26 04:27:47 +0000194 if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(),
195 false))
196 break;
Chris Lattner5c7f7862009-06-26 03:52:38 +0000197 continue;
198 }
199 }
200
Douglas Gregor39a8de12009-02-25 19:37:18 +0000201 // We don't have any tokens that form the beginning of a
202 // nested-name-specifier, so we're done.
203 break;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000204 }
Douglas Gregor39a8de12009-02-25 19:37:18 +0000205
206 return HasScopeSpecifier;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000207}
208
209/// ParseCXXIdExpression - Handle id-expression.
210///
211/// id-expression:
212/// unqualified-id
213/// qualified-id
214///
215/// unqualified-id:
216/// identifier
217/// operator-function-id
218/// conversion-function-id [TODO]
219/// '~' class-name [TODO]
Douglas Gregoredce4dd2009-06-30 22:34:41 +0000220/// template-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000221///
222/// qualified-id:
223/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
224/// '::' identifier
225/// '::' operator-function-id
Douglas Gregoredce4dd2009-06-30 22:34:41 +0000226/// '::' template-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000227///
228/// nested-name-specifier:
229/// type-name '::'
230/// namespace-name '::'
231/// nested-name-specifier identifier '::'
232/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
233///
234/// NOTE: The standard specifies that, for qualified-id, the parser does not
235/// expect:
236///
237/// '::' conversion-function-id
238/// '::' '~' class-name
239///
240/// This may cause a slight inconsistency on diagnostics:
241///
242/// class C {};
243/// namespace A {}
244/// void f() {
245/// :: A :: ~ C(); // Some Sema error about using destructor with a
246/// // namespace.
247/// :: ~ C(); // Some Parser error like 'unexpected ~'.
248/// }
249///
250/// We simplify the parser a bit and make it work like:
251///
252/// qualified-id:
253/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
254/// '::' unqualified-id
255///
256/// That way Sema can handle and report similar errors for namespaces and the
257/// global scope.
258///
Sebastian Redlebc07d52009-02-03 20:19:35 +0000259/// The isAddressOfOperand parameter indicates that this id-expression is a
260/// direct operand of the address-of operator. This is, besides member contexts,
261/// the only place where a qualified-id naming a non-static class member may
262/// appear.
263///
264Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000265 // qualified-id:
266 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
267 // '::' unqualified-id
268 //
269 CXXScopeSpec SS;
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000270 ParseOptionalCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000271
272 // unqualified-id:
273 // identifier
274 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000275 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000276 // '~' class-name [TODO]
Douglas Gregoredce4dd2009-06-30 22:34:41 +0000277 // template-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000278 //
279 switch (Tok.getKind()) {
280 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000281 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000282
283 case tok::identifier: {
284 // Consume the identifier so that we can see if it is followed by a '('.
285 IdentifierInfo &II = *Tok.getIdentifierInfo();
286 SourceLocation L = ConsumeToken();
Sebastian Redlebc07d52009-02-03 20:19:35 +0000287 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
288 &SS, isAddressOfOperand);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000289 }
290
291 case tok::kw_operator: {
292 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000293 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000294 return Actions.ActOnCXXOperatorFunctionIdExpr(
Sebastian Redlebc07d52009-02-03 20:19:35 +0000295 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
296 isAddressOfOperand);
Chris Lattner7452c6f2009-01-05 01:24:05 +0000297 if (TypeTy *Type = ParseConversionFunctionId())
Sebastian Redlcd965b92009-01-18 18:53:16 +0000298 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
Sebastian Redlebc07d52009-02-03 20:19:35 +0000299 Tok.is(tok::l_paren), SS,
300 isAddressOfOperand);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000301
Douglas Gregor2def4832008-11-17 20:34:05 +0000302 // We already complained about a bad conversion-function-id,
303 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000304 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000305 }
306
Douglas Gregoredce4dd2009-06-30 22:34:41 +0000307 case tok::annot_template_id: {
308 TemplateIdAnnotation *TemplateId
309 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
310 assert((TemplateId->Kind == TNK_Function_template ||
311 TemplateId->Kind == TNK_Dependent_template_name) &&
312 "A template type name is not an ID expression");
313
314 ASTTemplateArgsPtr TemplateArgsPtr(Actions,
315 TemplateId->getTemplateArgs(),
316 TemplateId->getTemplateArgIsType(),
317 TemplateId->NumArgs);
318
319 OwningExprResult Result
320 = Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template),
321 TemplateId->TemplateNameLoc,
322 TemplateId->LAngleLoc,
323 TemplateArgsPtr,
324 TemplateId->getTemplateArgLocations(),
325 TemplateId->RAngleLoc);
326 ConsumeToken(); // Consume the template-id token
327 return move(Result);
328 }
329
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000330 } // switch.
331
332 assert(0 && "The switch was supposed to take care everything.");
333}
334
Reid Spencer5f016e22007-07-11 17:01:13 +0000335/// ParseCXXCasts - This handles the various ways to cast expressions to another
336/// type.
337///
338/// postfix-expression: [C++ 5.2p1]
339/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
340/// 'static_cast' '<' type-name '>' '(' expression ')'
341/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
342/// 'const_cast' '<' type-name '>' '(' expression ')'
343///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000344Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000345 tok::TokenKind Kind = Tok.getKind();
346 const char *CastName = 0; // For error messages
347
348 switch (Kind) {
349 default: assert(0 && "Unknown C++ cast!"); abort();
350 case tok::kw_const_cast: CastName = "const_cast"; break;
351 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
352 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
353 case tok::kw_static_cast: CastName = "static_cast"; break;
354 }
355
356 SourceLocation OpLoc = ConsumeToken();
357 SourceLocation LAngleBracketLoc = Tok.getLocation();
358
359 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000360 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000361
Douglas Gregor809070a2009-02-18 17:45:20 +0000362 TypeResult CastTy = ParseTypeName();
Reid Spencer5f016e22007-07-11 17:01:13 +0000363 SourceLocation RAngleBracketLoc = Tok.getLocation();
364
Chris Lattner1ab3b962008-11-18 07:48:38 +0000365 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000366 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000367
368 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
369
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000370 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
371 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000372
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000373 OwningExprResult Result = ParseExpression();
374
375 // Match the ')'.
376 if (Result.isInvalid())
377 SkipUntil(tok::r_paren);
378
379 if (Tok.is(tok::r_paren))
380 RParenLoc = ConsumeParen();
381 else
382 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000383
Douglas Gregor809070a2009-02-18 17:45:20 +0000384 if (!Result.isInvalid() && !CastTy.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000385 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000386 LAngleBracketLoc, CastTy.get(),
Douglas Gregor809070a2009-02-18 17:45:20 +0000387 RAngleBracketLoc,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000388 LParenLoc, move(Result), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000389
Sebastian Redl20df9b72008-12-11 22:51:44 +0000390 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000391}
392
Sebastian Redlc42e1182008-11-11 11:37:55 +0000393/// ParseCXXTypeid - This handles the C++ typeid expression.
394///
395/// postfix-expression: [C++ 5.2p1]
396/// 'typeid' '(' expression ')'
397/// 'typeid' '(' type-id ')'
398///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000399Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000400 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
401
402 SourceLocation OpLoc = ConsumeToken();
403 SourceLocation LParenLoc = Tok.getLocation();
404 SourceLocation RParenLoc;
405
406 // typeid expressions are always parenthesized.
407 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
408 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000409 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000410
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000411 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000412
413 if (isTypeIdInParens()) {
Douglas Gregor809070a2009-02-18 17:45:20 +0000414 TypeResult Ty = ParseTypeName();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000415
416 // Match the ')'.
417 MatchRHSPunctuation(tok::r_paren, LParenLoc);
418
Douglas Gregor809070a2009-02-18 17:45:20 +0000419 if (Ty.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000420 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000421
422 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Douglas Gregor809070a2009-02-18 17:45:20 +0000423 Ty.get(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000424 } else {
Douglas Gregore0762c92009-06-19 23:52:42 +0000425 // C++0x [expr.typeid]p3:
426 // When typeid is applied to an expression other than an lvalue of a
427 // polymorphic class type [...] The expression is an unevaluated
428 // operand (Clause 5).
429 //
430 // Note that we can't tell whether the expression is an lvalue of a
431 // polymorphic class type until after we've parsed the expression, so
Douglas Gregorac7610d2009-06-22 20:57:11 +0000432 // we the expression is potentially potentially evaluated.
433 EnterExpressionEvaluationContext Unevaluated(Actions,
434 Action::PotentiallyPotentiallyEvaluated);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000435 Result = ParseExpression();
436
437 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000438 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000439 SkipUntil(tok::r_paren);
440 else {
441 MatchRHSPunctuation(tok::r_paren, LParenLoc);
442
443 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000444 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000445 }
446 }
447
Sebastian Redl20df9b72008-12-11 22:51:44 +0000448 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000449}
450
Reid Spencer5f016e22007-07-11 17:01:13 +0000451/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
452///
453/// boolean-literal: [C++ 2.13.5]
454/// 'true'
455/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000456Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000457 tok::TokenKind Kind = Tok.getKind();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000458 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Reid Spencer5f016e22007-07-11 17:01:13 +0000459}
Chris Lattner50dd2892008-02-26 00:51:44 +0000460
461/// ParseThrowExpression - This handles the C++ throw expression.
462///
463/// throw-expression: [C++ 15]
464/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000465Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000466 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000467 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000468
Chris Lattner2a2819a2008-04-06 06:02:23 +0000469 // If the current token isn't the start of an assignment-expression,
470 // then the expression is not present. This handles things like:
471 // "C ? throw : (void)42", which is crazy but legal.
472 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
473 case tok::semi:
474 case tok::r_paren:
475 case tok::r_square:
476 case tok::r_brace:
477 case tok::colon:
478 case tok::comma:
Sebastian Redlf53597f2009-03-15 17:47:39 +0000479 return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
Chris Lattner50dd2892008-02-26 00:51:44 +0000480
Chris Lattner2a2819a2008-04-06 06:02:23 +0000481 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000482 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000483 if (Expr.isInvalid()) return move(Expr);
Sebastian Redlf53597f2009-03-15 17:47:39 +0000484 return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000485 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000486}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000487
488/// ParseCXXThis - This handles the C++ 'this' pointer.
489///
490/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
491/// a non-lvalue expression whose value is the address of the object for which
492/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000493Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000494 assert(Tok.is(tok::kw_this) && "Not 'this'!");
495 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000496 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000497}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000498
499/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
500/// Can be interpreted either as function-style casting ("int(x)")
501/// or class type construction ("ClassType(x,y,z)")
502/// or creation of a value-initialized type ("int()").
503///
504/// postfix-expression: [C++ 5.2p1]
505/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
506/// typename-specifier '(' expression-list[opt] ')' [TODO]
507///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000508Parser::OwningExprResult
509Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000510 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000511 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000512
513 assert(Tok.is(tok::l_paren) && "Expected '('!");
514 SourceLocation LParenLoc = ConsumeParen();
515
Sebastian Redla55e52c2008-11-25 22:21:31 +0000516 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000517 CommaLocsTy CommaLocs;
518
519 if (Tok.isNot(tok::r_paren)) {
520 if (ParseExpressionList(Exprs, CommaLocs)) {
521 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000522 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000523 }
524 }
525
526 // Match the ')'.
527 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
528
Sebastian Redlef0cb8e2009-07-29 13:50:23 +0000529 // TypeRep could be null, if it references an invalid typedef.
530 if (!TypeRep)
531 return ExprError();
532
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000533 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
534 "Unexpected number of commas!");
Sebastian Redlf53597f2009-03-15 17:47:39 +0000535 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
536 LParenLoc, move_arg(Exprs),
Jay Foadbeaaccd2009-05-21 09:52:38 +0000537 CommaLocs.data(), RParenLoc);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000538}
539
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000540/// ParseCXXCondition - if/switch/while/for condition expression.
541///
542/// condition:
543/// expression
544/// type-specifier-seq declarator '=' assignment-expression
545/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
546/// '=' assignment-expression
547///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000548Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000549 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000550 return ParseExpression(); // expression
551
552 SourceLocation StartLoc = Tok.getLocation();
553
554 // type-specifier-seq
555 DeclSpec DS;
556 ParseSpecifierQualifierList(DS);
557
558 // declarator
559 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
560 ParseDeclarator(DeclaratorInfo);
561
562 // simple-asm-expr[opt]
563 if (Tok.is(tok::kw_asm)) {
Sebastian Redlab197ba2009-02-09 18:23:29 +0000564 SourceLocation Loc;
565 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000566 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000567 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000568 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000569 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000570 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000571 DeclaratorInfo.SetRangeEnd(Loc);
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000572 }
573
574 // If attributes are present, parse them.
Sebastian Redlab197ba2009-02-09 18:23:29 +0000575 if (Tok.is(tok::kw___attribute)) {
576 SourceLocation Loc;
577 AttributeList *AttrList = ParseAttributes(&Loc);
578 DeclaratorInfo.AddAttributes(AttrList, Loc);
579 }
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000580
581 // '=' assignment-expression
582 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000583 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000584 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000585 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000586 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000587 return ExprError();
588
Sebastian Redlf53597f2009-03-15 17:47:39 +0000589 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
590 DeclaratorInfo,EqualLoc,
591 move(AssignExpr));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000592}
593
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000594/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
595/// This should only be called when the current token is known to be part of
596/// simple-type-specifier.
597///
598/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000599/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000600/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
601/// char
602/// wchar_t
603/// bool
604/// short
605/// int
606/// long
607/// signed
608/// unsigned
609/// float
610/// double
611/// void
612/// [GNU] typeof-specifier
613/// [C++0x] auto [TODO]
614///
615/// type-name:
616/// class-name
617/// enum-name
618/// typedef-name
619///
620void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
621 DS.SetRangeStart(Tok.getLocation());
622 const char *PrevSpec;
John McCallfec54012009-08-03 20:12:06 +0000623 unsigned DiagID;
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000624 SourceLocation Loc = Tok.getLocation();
625
626 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000627 case tok::identifier: // foo::bar
628 case tok::coloncolon: // ::foo::bar
629 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000630 default:
631 assert(0 && "Not a simple-type-specifier token!");
632 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000633
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000634 // type-name
Chris Lattnerb31757b2009-01-06 05:06:21 +0000635 case tok::annot_typename: {
John McCallfec54012009-08-03 20:12:06 +0000636 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000637 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000638 break;
639 }
640
641 // builtin types
642 case tok::kw_short:
John McCallfec54012009-08-03 20:12:06 +0000643 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000644 break;
645 case tok::kw_long:
John McCallfec54012009-08-03 20:12:06 +0000646 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000647 break;
648 case tok::kw_signed:
John McCallfec54012009-08-03 20:12:06 +0000649 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000650 break;
651 case tok::kw_unsigned:
John McCallfec54012009-08-03 20:12:06 +0000652 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000653 break;
654 case tok::kw_void:
John McCallfec54012009-08-03 20:12:06 +0000655 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000656 break;
657 case tok::kw_char:
John McCallfec54012009-08-03 20:12:06 +0000658 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000659 break;
660 case tok::kw_int:
John McCallfec54012009-08-03 20:12:06 +0000661 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000662 break;
663 case tok::kw_float:
John McCallfec54012009-08-03 20:12:06 +0000664 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000665 break;
666 case tok::kw_double:
John McCallfec54012009-08-03 20:12:06 +0000667 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000668 break;
669 case tok::kw_wchar_t:
John McCallfec54012009-08-03 20:12:06 +0000670 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000671 break;
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000672 case tok::kw_char16_t:
John McCallfec54012009-08-03 20:12:06 +0000673 DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000674 break;
675 case tok::kw_char32_t:
John McCallfec54012009-08-03 20:12:06 +0000676 DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000677 break;
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000678 case tok::kw_bool:
John McCallfec54012009-08-03 20:12:06 +0000679 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000680 break;
681
682 // GNU typeof support.
683 case tok::kw_typeof:
684 ParseTypeofSpecifier(DS);
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000685 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000686 return;
687 }
Chris Lattnerb31757b2009-01-06 05:06:21 +0000688 if (Tok.is(tok::annot_typename))
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000689 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
690 else
691 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000692 ConsumeToken();
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000693 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000694}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000695
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000696/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
697/// [dcl.name]), which is a non-empty sequence of type-specifiers,
698/// e.g., "const short int". Note that the DeclSpec is *not* finished
699/// by parsing the type-specifier-seq, because these sequences are
700/// typically followed by some form of declarator. Returns true and
701/// emits diagnostics if this is not a type-specifier-seq, false
702/// otherwise.
703///
704/// type-specifier-seq: [C++ 8.1]
705/// type-specifier type-specifier-seq[opt]
706///
707bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
708 DS.SetRangeStart(Tok.getLocation());
709 const char *PrevSpec = 0;
John McCallfec54012009-08-03 20:12:06 +0000710 unsigned DiagID;
711 bool isInvalid = 0;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000712
713 // Parse one or more of the type specifiers.
John McCallfec54012009-08-03 20:12:06 +0000714 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000715 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000716 return true;
717 }
Chris Lattner7a0ab5f2009-01-06 06:59:53 +0000718
John McCallfec54012009-08-03 20:12:06 +0000719 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000720
721 return false;
722}
723
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000724/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000725/// operator name (C++ [over.oper]). If successful, returns the
726/// predefined identifier that corresponds to that overloaded
727/// operator. Otherwise, returns NULL and does not consume any tokens.
728///
729/// operator-function-id: [C++ 13.5]
730/// 'operator' operator
731///
732/// operator: one of
733/// new delete new[] delete[]
734/// + - * / % ^ & | ~
735/// ! = < > += -= *= /= %=
736/// ^= &= |= << >> >>= <<= == !=
737/// <= >= && || ++ -- , ->* ->
738/// () []
Sebastian Redlab197ba2009-02-09 18:23:29 +0000739OverloadedOperatorKind
740Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000741 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Sebastian Redlab197ba2009-02-09 18:23:29 +0000742 SourceLocation Loc;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000743
744 OverloadedOperatorKind Op = OO_None;
745 switch (NextToken().getKind()) {
746 case tok::kw_new:
747 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000748 Loc = ConsumeToken(); // 'new'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000749 if (Tok.is(tok::l_square)) {
750 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000751 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000752 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
753 Op = OO_Array_New;
754 } else {
755 Op = OO_New;
756 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000757 if (EndLoc)
758 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000759 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000760
761 case tok::kw_delete:
762 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000763 Loc = ConsumeToken(); // 'delete'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000764 if (Tok.is(tok::l_square)) {
765 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000766 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000767 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
768 Op = OO_Array_Delete;
769 } else {
770 Op = OO_Delete;
771 }
Sebastian Redlab197ba2009-02-09 18:23:29 +0000772 if (EndLoc)
773 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000774 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000775
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000776#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000777 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000778#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000779#include "clang/Basic/OperatorKinds.def"
780
781 case tok::l_paren:
782 ConsumeToken(); // 'operator'
783 ConsumeParen(); // '('
Sebastian Redlab197ba2009-02-09 18:23:29 +0000784 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000785 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000786 if (EndLoc)
787 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000788 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000789
790 case tok::l_square:
791 ConsumeToken(); // 'operator'
792 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +0000793 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000794 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000795 if (EndLoc)
796 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000797 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000798
799 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000800 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000801 }
802
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000803 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +0000804 Loc = ConsumeAnyToken(); // the operator itself
805 if (EndLoc)
806 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000807 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000808}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000809
810/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
811/// which expresses the name of a user-defined conversion operator
812/// (C++ [class.conv.fct]p1). Returns the type that this operator is
813/// specifying a conversion for, or NULL if there was an error.
814///
815/// conversion-function-id: [C++ 12.3.2]
816/// operator conversion-type-id
817///
818/// conversion-type-id:
819/// type-specifier-seq conversion-declarator[opt]
820///
821/// conversion-declarator:
822/// ptr-operator conversion-declarator[opt]
Sebastian Redlab197ba2009-02-09 18:23:29 +0000823Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000824 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
825 ConsumeToken(); // 'operator'
826
827 // Parse the type-specifier-seq.
828 DeclSpec DS;
829 if (ParseCXXTypeSpecifierSeq(DS))
830 return 0;
831
832 // Parse the conversion-declarator, which is merely a sequence of
833 // ptr-operators.
834 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000835 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000836 if (EndLoc)
837 *EndLoc = D.getSourceRange().getEnd();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000838
839 // Finish up the type.
840 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000841 if (Result.isInvalid())
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000842 return 0;
843 else
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000844 return Result.get();
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000845}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000846
847/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
848/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000849///
850/// This method is called to parse the new expression after the optional :: has
851/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
852/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000853///
854/// new-expression:
855/// '::'[opt] 'new' new-placement[opt] new-type-id
856/// new-initializer[opt]
857/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
858/// new-initializer[opt]
859///
860/// new-placement:
861/// '(' expression-list ')'
862///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000863/// new-type-id:
864/// type-specifier-seq new-declarator[opt]
865///
866/// new-declarator:
867/// ptr-operator new-declarator[opt]
868/// direct-new-declarator
869///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000870/// new-initializer:
871/// '(' expression-list[opt] ')'
872/// [C++0x] braced-init-list [TODO]
873///
Chris Lattner59232d32009-01-04 21:25:24 +0000874Parser::OwningExprResult
875Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
876 assert(Tok.is(tok::kw_new) && "expected 'new' token");
877 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000878
879 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
880 // second form of new-expression. It can't be a new-type-id.
881
Sebastian Redla55e52c2008-11-25 22:21:31 +0000882 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000883 SourceLocation PlacementLParen, PlacementRParen;
884
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000885 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000886 DeclSpec DS;
887 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000888 if (Tok.is(tok::l_paren)) {
889 // If it turns out to be a placement, we change the type location.
890 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000891 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
892 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000893 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000894 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000895
896 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000897 if (PlacementRParen.isInvalid()) {
898 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000899 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000900 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000901
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000902 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000903 // Reset the placement locations. There was no placement.
904 PlacementLParen = PlacementRParen = SourceLocation();
905 ParenTypeId = true;
906 } else {
907 // We still need the type.
908 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000909 SourceLocation LParen = ConsumeParen();
910 ParseSpecifierQualifierList(DS);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000911 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000912 ParseDeclarator(DeclaratorInfo);
913 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000914 ParenTypeId = true;
915 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000916 if (ParseCXXTypeSpecifierSeq(DS))
917 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000918 else {
919 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000920 ParseDeclaratorInternal(DeclaratorInfo,
921 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000922 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000923 ParenTypeId = false;
924 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000925 }
926 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000927 // A new-type-id is a simplified type-id, where essentially the
928 // direct-declarator is replaced by a direct-new-declarator.
929 if (ParseCXXTypeSpecifierSeq(DS))
930 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000931 else {
932 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000933 ParseDeclaratorInternal(DeclaratorInfo,
934 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +0000935 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000936 ParenTypeId = false;
937 }
Chris Lattnereaaebc72009-04-25 08:06:05 +0000938 if (DeclaratorInfo.isInvalidType()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000939 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000940 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000941 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000942
Sebastian Redla55e52c2008-11-25 22:21:31 +0000943 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000944 SourceLocation ConstructorLParen, ConstructorRParen;
945
946 if (Tok.is(tok::l_paren)) {
947 ConstructorLParen = ConsumeParen();
948 if (Tok.isNot(tok::r_paren)) {
949 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000950 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
951 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000952 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000953 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000954 }
955 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000956 if (ConstructorRParen.isInvalid()) {
957 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000958 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000959 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000960 }
961
Sebastian Redlf53597f2009-03-15 17:47:39 +0000962 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
963 move_arg(PlacementArgs), PlacementRParen,
964 ParenTypeId, DeclaratorInfo, ConstructorLParen,
965 move_arg(ConstructorArgs), ConstructorRParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000966}
967
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000968/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
969/// passed to ParseDeclaratorInternal.
970///
971/// direct-new-declarator:
972/// '[' expression ']'
973/// direct-new-declarator '[' constant-expression ']'
974///
Chris Lattner59232d32009-01-04 21:25:24 +0000975void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000976 // Parse the array dimensions.
977 bool first = true;
978 while (Tok.is(tok::l_square)) {
979 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000980 OwningExprResult Size(first ? ParseExpression()
981 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000982 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000983 // Recover
984 SkipUntil(tok::r_square);
985 return;
986 }
987 first = false;
988
Sebastian Redlab197ba2009-02-09 18:23:29 +0000989 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000990 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +0000991 Size.release(), LLoc, RLoc),
Sebastian Redlab197ba2009-02-09 18:23:29 +0000992 RLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000993
Sebastian Redlab197ba2009-02-09 18:23:29 +0000994 if (RLoc.isInvalid())
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000995 return;
996 }
997}
998
999/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
1000/// This ambiguity appears in the syntax of the C++ new operator.
1001///
1002/// new-expression:
1003/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
1004/// new-initializer[opt]
1005///
1006/// new-placement:
1007/// '(' expression-list ')'
1008///
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001009bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +00001010 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001011 // The '(' was already consumed.
1012 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001013 ParseSpecifierQualifierList(D.getMutableDeclSpec());
Sebastian Redlab197ba2009-02-09 18:23:29 +00001014 D.SetSourceRange(D.getDeclSpec().getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001015 ParseDeclarator(D);
Chris Lattnereaaebc72009-04-25 08:06:05 +00001016 return D.isInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001017 }
1018
1019 // It's not a type, it has to be an expression list.
1020 // Discard the comma locations - ActOnCXXNew has enough parameters.
1021 CommaLocsTy CommaLocs;
1022 return ParseExpressionList(PlacementArgs, CommaLocs);
1023}
1024
1025/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
1026/// to free memory allocated by new.
1027///
Chris Lattner59232d32009-01-04 21:25:24 +00001028/// This method is called to parse the 'delete' expression after the optional
1029/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
1030/// and "Start" is its location. Otherwise, "Start" is the location of the
1031/// 'delete' token.
1032///
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001033/// delete-expression:
1034/// '::'[opt] 'delete' cast-expression
1035/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +00001036Parser::OwningExprResult
1037Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
1038 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
1039 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001040
1041 // Array delete?
1042 bool ArrayDelete = false;
1043 if (Tok.is(tok::l_square)) {
1044 ArrayDelete = true;
1045 SourceLocation LHS = ConsumeBracket();
1046 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
1047 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +00001048 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001049 }
1050
Sebastian Redl2f7ece72008-12-11 21:36:32 +00001051 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +00001052 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +00001053 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001054
Sebastian Redlf53597f2009-03-15 17:47:39 +00001055 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001056}
Sebastian Redl64b45f72009-01-05 20:52:13 +00001057
1058static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
1059{
1060 switch(kind) {
1061 default: assert(false && "Not a known unary type trait.");
1062 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
1063 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
1064 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
1065 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
1066 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
1067 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
1068 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
1069 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
1070 case tok::kw___is_abstract: return UTT_IsAbstract;
1071 case tok::kw___is_class: return UTT_IsClass;
1072 case tok::kw___is_empty: return UTT_IsEmpty;
1073 case tok::kw___is_enum: return UTT_IsEnum;
1074 case tok::kw___is_pod: return UTT_IsPOD;
1075 case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
1076 case tok::kw___is_union: return UTT_IsUnion;
1077 }
1078}
1079
1080/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
1081/// pseudo-functions that allow implementation of the TR1/C++0x type traits
1082/// templates.
1083///
1084/// primary-expression:
1085/// [GNU] unary-type-trait '(' type-id ')'
1086///
1087Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
1088{
1089 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
1090 SourceLocation Loc = ConsumeToken();
1091
1092 SourceLocation LParen = Tok.getLocation();
1093 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1094 return ExprError();
1095
1096 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
1097 // there will be cryptic errors about mismatched parentheses and missing
1098 // specifiers.
Douglas Gregor809070a2009-02-18 17:45:20 +00001099 TypeResult Ty = ParseTypeName();
Sebastian Redl64b45f72009-01-05 20:52:13 +00001100
1101 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
1102
Douglas Gregor809070a2009-02-18 17:45:20 +00001103 if (Ty.isInvalid())
1104 return ExprError();
1105
1106 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
Sebastian Redl64b45f72009-01-05 20:52:13 +00001107}
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001108
1109/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
1110/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
1111/// based on the context past the parens.
1112Parser::OwningExprResult
1113Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
1114 TypeTy *&CastTy,
1115 SourceLocation LParenLoc,
1116 SourceLocation &RParenLoc) {
1117 assert(getLang().CPlusPlus && "Should only be called for C++!");
1118 assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
1119 assert(isTypeIdInParens() && "Not a type-id!");
1120
1121 OwningExprResult Result(Actions, true);
1122 CastTy = 0;
1123
1124 // We need to disambiguate a very ugly part of the C++ syntax:
1125 //
1126 // (T())x; - type-id
1127 // (T())*x; - type-id
1128 // (T())/x; - expression
1129 // (T()); - expression
1130 //
1131 // The bad news is that we cannot use the specialized tentative parser, since
1132 // it can only verify that the thing inside the parens can be parsed as
1133 // type-id, it is not useful for determining the context past the parens.
1134 //
1135 // The good news is that the parser can disambiguate this part without
Argyrios Kyrtzidisa558a892009-05-22 15:12:46 +00001136 // making any unnecessary Action calls.
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001137 //
1138 // It uses a scheme similar to parsing inline methods. The parenthesized
1139 // tokens are cached, the context that follows is determined (possibly by
1140 // parsing a cast-expression), and then we re-introduce the cached tokens
1141 // into the token stream and parse them appropriately.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001142
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001143 ParenParseOption ParseAs;
1144 CachedTokens Toks;
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001145
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001146 // Store the tokens of the parentheses. We will parse them after we determine
1147 // the context that follows them.
1148 if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
1149 // We didn't find the ')' we expected.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001150 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1151 return ExprError();
1152 }
1153
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001154 if (Tok.is(tok::l_brace)) {
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001155 ParseAs = CompoundLiteral;
1156 } else {
1157 bool NotCastExpr;
Eli Friedmanb53f08a2009-05-25 19:41:42 +00001158 // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
1159 if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
1160 NotCastExpr = true;
1161 } else {
1162 // Try parsing the cast-expression that may follow.
1163 // If it is not a cast-expression, NotCastExpr will be true and no token
1164 // will be consumed.
1165 Result = ParseCastExpression(false/*isUnaryExpression*/,
1166 false/*isAddressofOperand*/,
Nate Begeman2ef13e52009-08-10 23:49:36 +00001167 NotCastExpr, false);
Eli Friedmanb53f08a2009-05-25 19:41:42 +00001168 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001169
1170 // If we parsed a cast-expression, it's really a type-id, otherwise it's
1171 // an expression.
1172 ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001173 }
1174
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001175 // The current token should go after the cached tokens.
1176 Toks.push_back(Tok);
1177 // Re-enter the stored parenthesized tokens into the token stream, so we may
1178 // parse them now.
1179 PP.EnterTokenStream(Toks.data(), Toks.size(),
1180 true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
1181 // Drop the current token and bring the first cached one. It's the same token
1182 // as when we entered this function.
1183 ConsumeAnyToken();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001184
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001185 if (ParseAs >= CompoundLiteral) {
1186 TypeResult Ty = ParseTypeName();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001187
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001188 // Match the ')'.
1189 if (Tok.is(tok::r_paren))
1190 RParenLoc = ConsumeParen();
1191 else
1192 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001193
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001194 if (ParseAs == CompoundLiteral) {
1195 ExprType = CompoundLiteral;
1196 return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
1197 }
1198
1199 // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
1200 assert(ParseAs == CastExpr);
1201
1202 if (Ty.isInvalid())
1203 return ExprError();
1204
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001205 CastTy = Ty.get();
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001206
1207 // Result is what ParseCastExpression returned earlier.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001208 if (!Result.isInvalid())
Nate Begeman2ef13e52009-08-10 23:49:36 +00001209 Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
1210 move(Result));
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001211 return move(Result);
1212 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001213
1214 // Not a compound literal, and not followed by a cast-expression.
1215 assert(ParseAs == SimpleExpr);
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001216
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001217 ExprType = SimpleExpr;
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001218 Result = ParseExpression();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001219 if (!Result.isInvalid() && Tok.is(tok::r_paren))
1220 Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
1221
1222 // Match the ')'.
1223 if (Result.isInvalid()) {
1224 SkipUntil(tok::r_paren);
1225 return ExprError();
1226 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001227
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001228 if (Tok.is(tok::r_paren))
1229 RParenLoc = ConsumeParen();
1230 else
1231 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1232
1233 return move(Result);
1234}