blob: d0e2f70319d133c140eddae0483d68e52369962d [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"
Douglas Gregor3f9a0562009-11-03 01:35:08 +000017#include "llvm/Support/ErrorHandling.h"
18
Reid Spencer5f016e22007-07-11 17:01:13 +000019using namespace clang;
20
Mike Stump1eb44332009-09-09 15:08:12 +000021/// \brief Parse global scope or nested-name-specifier if present.
Douglas Gregor2dd078a2009-09-02 22:59:36 +000022///
23/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
Mike Stump1eb44332009-09-09 15:08:12 +000024/// may be preceded by '::'). Note that this routine will not parse ::new or
Douglas Gregor2dd078a2009-09-02 22:59:36 +000025/// ::delete; it will just leave them in the token stream.
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000026///
27/// '::'[opt] nested-name-specifier
28/// '::'
29///
30/// nested-name-specifier:
31/// type-name '::'
32/// namespace-name '::'
33/// nested-name-specifier identifier '::'
Douglas Gregor2dd078a2009-09-02 22:59:36 +000034/// nested-name-specifier 'template'[opt] simple-template-id '::'
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000035///
Douglas Gregor2dd078a2009-09-02 22:59:36 +000036///
Mike Stump1eb44332009-09-09 15:08:12 +000037/// \param SS the scope specifier that will be set to the parsed
Douglas Gregor2dd078a2009-09-02 22:59:36 +000038/// nested-name-specifier (or empty)
39///
Mike Stump1eb44332009-09-09 15:08:12 +000040/// \param ObjectType if this nested-name-specifier is being parsed following
Douglas Gregor2dd078a2009-09-02 22:59:36 +000041/// the "." or "->" of a member access expression, this parameter provides the
42/// type of the object whose members are being accessed.
43///
44/// \param EnteringContext whether we will be entering into the context of
45/// the nested-name-specifier after parsing it.
46///
47/// \returns true if a scope specifier was parsed.
Douglas Gregor495c35d2009-08-25 22:51:20 +000048bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Douglas Gregor2dd078a2009-09-02 22:59:36 +000049 Action::TypeTy *ObjectType,
Douglas Gregor495c35d2009-08-25 22:51:20 +000050 bool EnteringContext) {
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000051 assert(getLang().CPlusPlus &&
Chris Lattner7452c6f2009-01-05 01:24:05 +000052 "Call sites of this function should be guarded by checking for C++");
Mike Stump1eb44332009-09-09 15:08:12 +000053
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000054 if (Tok.is(tok::annot_cxxscope)) {
Douglas Gregor35073692009-03-26 23:56:24 +000055 SS.setScopeRep(Tok.getAnnotationValue());
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000056 SS.setRange(Tok.getAnnotationRange());
57 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000058 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000059 }
Chris Lattnere607e802009-01-04 21:14:15 +000060
Douglas Gregor39a8de12009-02-25 19:37:18 +000061 bool HasScopeSpecifier = false;
62
Chris Lattner5b454732009-01-05 03:55:46 +000063 if (Tok.is(tok::coloncolon)) {
64 // ::new and ::delete aren't nested-name-specifiers.
65 tok::TokenKind NextKind = NextToken().getKind();
66 if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
67 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000068
Chris Lattner55a7cef2009-01-05 00:13:00 +000069 // '::' - Global scope qualifier.
Chris Lattner357089d2009-01-05 02:07:19 +000070 SourceLocation CCLoc = ConsumeToken();
Chris Lattner357089d2009-01-05 02:07:19 +000071 SS.setBeginLoc(CCLoc);
Douglas Gregor35073692009-03-26 23:56:24 +000072 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
Chris Lattner357089d2009-01-05 02:07:19 +000073 SS.setEndLoc(CCLoc);
Douglas Gregor39a8de12009-02-25 19:37:18 +000074 HasScopeSpecifier = true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000075 }
76
Douglas Gregor39a8de12009-02-25 19:37:18 +000077 while (true) {
Douglas Gregor2dd078a2009-09-02 22:59:36 +000078 if (HasScopeSpecifier) {
79 // C++ [basic.lookup.classref]p5:
80 // If the qualified-id has the form
Douglas Gregor3b6afbb2009-09-09 00:23:06 +000081 //
Douglas Gregor2dd078a2009-09-02 22:59:36 +000082 // ::class-name-or-namespace-name::...
Douglas Gregor3b6afbb2009-09-09 00:23:06 +000083 //
Douglas Gregor2dd078a2009-09-02 22:59:36 +000084 // the class-name-or-namespace-name is looked up in global scope as a
85 // class-name or namespace-name.
86 //
87 // To implement this, we clear out the object type as soon as we've
88 // seen a leading '::' or part of a nested-name-specifier.
89 ObjectType = 0;
Douglas Gregor81b747b2009-09-17 21:32:03 +000090
91 if (Tok.is(tok::code_completion)) {
92 // Code completion for a nested-name-specifier, where the code
93 // code completion token follows the '::'.
94 Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
95 ConsumeToken();
96 }
Douglas Gregor2dd078a2009-09-02 22:59:36 +000097 }
Mike Stump1eb44332009-09-09 15:08:12 +000098
Douglas Gregor39a8de12009-02-25 19:37:18 +000099 // nested-name-specifier:
Chris Lattner77cf72a2009-06-26 03:47:46 +0000100 // nested-name-specifier 'template'[opt] simple-template-id '::'
101
102 // Parse the optional 'template' keyword, then make sure we have
103 // 'identifier <' after it.
104 if (Tok.is(tok::kw_template)) {
Douglas Gregor2dd078a2009-09-02 22:59:36 +0000105 // If we don't have a scope specifier or an object type, this isn't a
Eli Friedmaneab975d2009-08-29 04:08:08 +0000106 // nested-name-specifier, since they aren't allowed to start with
107 // 'template'.
Douglas Gregor2dd078a2009-09-02 22:59:36 +0000108 if (!HasScopeSpecifier && !ObjectType)
Eli Friedmaneab975d2009-08-29 04:08:08 +0000109 break;
110
Chris Lattner77cf72a2009-06-26 03:47:46 +0000111 SourceLocation TemplateKWLoc = ConsumeToken();
Mike Stump1eb44332009-09-09 15:08:12 +0000112
Chris Lattner77cf72a2009-06-26 03:47:46 +0000113 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000114 Diag(Tok.getLocation(),
Chris Lattner77cf72a2009-06-26 03:47:46 +0000115 diag::err_id_after_template_in_nested_name_spec)
116 << SourceRange(TemplateKWLoc);
117 break;
118 }
Mike Stump1eb44332009-09-09 15:08:12 +0000119
Chris Lattner77cf72a2009-06-26 03:47:46 +0000120 if (NextToken().isNot(tok::less)) {
121 Diag(NextToken().getLocation(),
122 diag::err_less_after_template_name_in_nested_name_spec)
123 << Tok.getIdentifierInfo()->getName()
124 << SourceRange(TemplateKWLoc, Tok.getLocation());
125 break;
126 }
Mike Stump1eb44332009-09-09 15:08:12 +0000127
Douglas Gregor014e88d2009-11-03 23:16:33 +0000128 UnqualifiedId TemplateName;
129 TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
Mike Stump1eb44332009-09-09 15:08:12 +0000130 TemplateTy Template
Douglas Gregor014e88d2009-11-03 23:16:33 +0000131 = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
Douglas Gregor2dd078a2009-09-02 22:59:36 +0000132 ObjectType);
Eli Friedmaneab975d2009-08-29 04:08:08 +0000133 if (!Template)
134 break;
Chris Lattnerc8e27cc2009-06-26 04:27:47 +0000135 if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
136 &SS, TemplateKWLoc, false))
137 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000138
Chris Lattner77cf72a2009-06-26 03:47:46 +0000139 continue;
140 }
Mike Stump1eb44332009-09-09 15:08:12 +0000141
Douglas Gregor39a8de12009-02-25 19:37:18 +0000142 if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000143 // We have
Douglas Gregor39a8de12009-02-25 19:37:18 +0000144 //
145 // simple-template-id '::'
146 //
147 // So we need to check whether the simple-template-id is of the
Douglas Gregorc45c2322009-03-31 00:43:58 +0000148 // right kind (it should name a type or be dependent), and then
149 // convert it into a type within the nested-name-specifier.
Mike Stump1eb44332009-09-09 15:08:12 +0000150 TemplateIdAnnotation *TemplateId
Douglas Gregor39a8de12009-02-25 19:37:18 +0000151 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
152
Mike Stump1eb44332009-09-09 15:08:12 +0000153 if (TemplateId->Kind == TNK_Type_template ||
Douglas Gregorc45c2322009-03-31 00:43:58 +0000154 TemplateId->Kind == TNK_Dependent_template_name) {
Douglas Gregor31a19b62009-04-01 21:51:26 +0000155 AnnotateTemplateIdTokenAsType(&SS);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000156
Mike Stump1eb44332009-09-09 15:08:12 +0000157 assert(Tok.is(tok::annot_typename) &&
Douglas Gregor39a8de12009-02-25 19:37:18 +0000158 "AnnotateTemplateIdTokenAsType isn't working");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000159 Token TypeToken = Tok;
160 ConsumeToken();
161 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
162 SourceLocation CCLoc = ConsumeToken();
Mike Stump1eb44332009-09-09 15:08:12 +0000163
Douglas Gregor39a8de12009-02-25 19:37:18 +0000164 if (!HasScopeSpecifier) {
165 SS.setBeginLoc(TypeToken.getLocation());
166 HasScopeSpecifier = true;
167 }
Mike Stump1eb44332009-09-09 15:08:12 +0000168
Douglas Gregor31a19b62009-04-01 21:51:26 +0000169 if (TypeToken.getAnnotationValue())
170 SS.setScopeRep(
Mike Stump1eb44332009-09-09 15:08:12 +0000171 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
Douglas Gregor31a19b62009-04-01 21:51:26 +0000172 TypeToken.getAnnotationValue(),
173 TypeToken.getAnnotationRange(),
174 CCLoc));
175 else
176 SS.setScopeRep(0);
Douglas Gregor39a8de12009-02-25 19:37:18 +0000177 SS.setEndLoc(CCLoc);
178 continue;
Chris Lattner67b9e832009-06-26 03:45:46 +0000179 }
Mike Stump1eb44332009-09-09 15:08:12 +0000180
Chris Lattner67b9e832009-06-26 03:45:46 +0000181 assert(false && "FIXME: Only type template names supported here");
Douglas Gregor39a8de12009-02-25 19:37:18 +0000182 }
183
Chris Lattner5c7f7862009-06-26 03:52:38 +0000184
185 // The rest of the nested-name-specifier possibilities start with
186 // tok::identifier.
187 if (Tok.isNot(tok::identifier))
188 break;
189
190 IdentifierInfo &II = *Tok.getIdentifierInfo();
191
192 // nested-name-specifier:
193 // type-name '::'
194 // namespace-name '::'
195 // nested-name-specifier identifier '::'
196 Token Next = NextToken();
197 if (Next.is(tok::coloncolon)) {
198 // We have an identifier followed by a '::'. Lookup this name
199 // as the name in a nested-name-specifier.
200 SourceLocation IdLoc = ConsumeToken();
201 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
202 SourceLocation CCLoc = ConsumeToken();
Mike Stump1eb44332009-09-09 15:08:12 +0000203
Chris Lattner5c7f7862009-06-26 03:52:38 +0000204 if (!HasScopeSpecifier) {
205 SS.setBeginLoc(IdLoc);
206 HasScopeSpecifier = true;
207 }
Mike Stump1eb44332009-09-09 15:08:12 +0000208
Chris Lattner5c7f7862009-06-26 03:52:38 +0000209 if (SS.isInvalid())
210 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000211
Chris Lattner5c7f7862009-06-26 03:52:38 +0000212 SS.setScopeRep(
Douglas Gregor495c35d2009-08-25 22:51:20 +0000213 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
Douglas Gregor2dd078a2009-09-02 22:59:36 +0000214 ObjectType, EnteringContext));
Chris Lattner5c7f7862009-06-26 03:52:38 +0000215 SS.setEndLoc(CCLoc);
216 continue;
217 }
Mike Stump1eb44332009-09-09 15:08:12 +0000218
Chris Lattner5c7f7862009-06-26 03:52:38 +0000219 // nested-name-specifier:
220 // type-name '<'
221 if (Next.is(tok::less)) {
222 TemplateTy Template;
Douglas Gregor014e88d2009-11-03 23:16:33 +0000223 UnqualifiedId TemplateName;
224 TemplateName.setIdentifier(&II, Tok.getLocation());
225 if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS,
226 TemplateName,
Douglas Gregor2dd078a2009-09-02 22:59:36 +0000227 ObjectType,
Douglas Gregor495c35d2009-08-25 22:51:20 +0000228 EnteringContext,
229 Template)) {
Chris Lattner5c7f7862009-06-26 03:52:38 +0000230 // We have found a template name, so annotate this this token
231 // with a template-id annotation. We do not permit the
232 // template-id to be translated into a type annotation,
233 // because some clients (e.g., the parsing of class template
234 // specializations) still want to see the original template-id
235 // token.
Chris Lattnerc8e27cc2009-06-26 04:27:47 +0000236 if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(),
237 false))
238 break;
Chris Lattner5c7f7862009-06-26 03:52:38 +0000239 continue;
240 }
241 }
242
Douglas Gregor39a8de12009-02-25 19:37:18 +0000243 // We don't have any tokens that form the beginning of a
244 // nested-name-specifier, so we're done.
245 break;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000246 }
Mike Stump1eb44332009-09-09 15:08:12 +0000247
Douglas Gregor39a8de12009-02-25 19:37:18 +0000248 return HasScopeSpecifier;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000249}
250
251/// ParseCXXIdExpression - Handle id-expression.
252///
253/// id-expression:
254/// unqualified-id
255/// qualified-id
256///
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000257/// qualified-id:
258/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
259/// '::' identifier
260/// '::' operator-function-id
Douglas Gregoredce4dd2009-06-30 22:34:41 +0000261/// '::' template-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000262///
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000263/// NOTE: The standard specifies that, for qualified-id, the parser does not
264/// expect:
265///
266/// '::' conversion-function-id
267/// '::' '~' class-name
268///
269/// This may cause a slight inconsistency on diagnostics:
270///
271/// class C {};
272/// namespace A {}
273/// void f() {
274/// :: A :: ~ C(); // Some Sema error about using destructor with a
275/// // namespace.
276/// :: ~ C(); // Some Parser error like 'unexpected ~'.
277/// }
278///
279/// We simplify the parser a bit and make it work like:
280///
281/// qualified-id:
282/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
283/// '::' unqualified-id
284///
285/// That way Sema can handle and report similar errors for namespaces and the
286/// global scope.
287///
Sebastian Redlebc07d52009-02-03 20:19:35 +0000288/// The isAddressOfOperand parameter indicates that this id-expression is a
289/// direct operand of the address-of operator. This is, besides member contexts,
290/// the only place where a qualified-id naming a non-static class member may
291/// appear.
292///
293Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000294 // qualified-id:
295 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
296 // '::' unqualified-id
297 //
298 CXXScopeSpec SS;
Douglas Gregor2dd078a2009-09-02 22:59:36 +0000299 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
Douglas Gregor02a24ee2009-11-03 16:56:39 +0000300
301 UnqualifiedId Name;
302 if (ParseUnqualifiedId(SS,
303 /*EnteringContext=*/false,
304 /*AllowDestructorName=*/false,
305 /*AllowConstructorName=*/false,
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000306 /*ObjectType=*/0,
Douglas Gregor02a24ee2009-11-03 16:56:39 +0000307 Name))
308 return ExprError();
309
310 return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
311 isAddressOfOperand);
312
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000313}
314
Reid Spencer5f016e22007-07-11 17:01:13 +0000315/// ParseCXXCasts - This handles the various ways to cast expressions to another
316/// type.
317///
318/// postfix-expression: [C++ 5.2p1]
319/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
320/// 'static_cast' '<' type-name '>' '(' expression ')'
321/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
322/// 'const_cast' '<' type-name '>' '(' expression ')'
323///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000324Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000325 tok::TokenKind Kind = Tok.getKind();
326 const char *CastName = 0; // For error messages
327
328 switch (Kind) {
329 default: assert(0 && "Unknown C++ cast!"); abort();
330 case tok::kw_const_cast: CastName = "const_cast"; break;
331 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
332 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
333 case tok::kw_static_cast: CastName = "static_cast"; break;
334 }
335
336 SourceLocation OpLoc = ConsumeToken();
337 SourceLocation LAngleBracketLoc = Tok.getLocation();
338
339 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000340 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000341
Douglas Gregor809070a2009-02-18 17:45:20 +0000342 TypeResult CastTy = ParseTypeName();
Reid Spencer5f016e22007-07-11 17:01:13 +0000343 SourceLocation RAngleBracketLoc = Tok.getLocation();
344
Chris Lattner1ab3b962008-11-18 07:48:38 +0000345 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000346 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000347
348 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
349
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000350 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
351 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000352
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000353 OwningExprResult Result = ParseExpression();
Mike Stump1eb44332009-09-09 15:08:12 +0000354
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000355 // Match the ')'.
356 if (Result.isInvalid())
357 SkipUntil(tok::r_paren);
Mike Stump1eb44332009-09-09 15:08:12 +0000358
Argyrios Kyrtzidis21e7ad22009-05-22 10:23:16 +0000359 if (Tok.is(tok::r_paren))
360 RParenLoc = ConsumeParen();
361 else
362 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000363
Douglas Gregor809070a2009-02-18 17:45:20 +0000364 if (!Result.isInvalid() && !CastTy.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000365 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000366 LAngleBracketLoc, CastTy.get(),
Douglas Gregor809070a2009-02-18 17:45:20 +0000367 RAngleBracketLoc,
Sebastian Redlf53597f2009-03-15 17:47:39 +0000368 LParenLoc, move(Result), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000369
Sebastian Redl20df9b72008-12-11 22:51:44 +0000370 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000371}
372
Sebastian Redlc42e1182008-11-11 11:37:55 +0000373/// ParseCXXTypeid - This handles the C++ typeid expression.
374///
375/// postfix-expression: [C++ 5.2p1]
376/// 'typeid' '(' expression ')'
377/// 'typeid' '(' type-id ')'
378///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000379Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000380 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
381
382 SourceLocation OpLoc = ConsumeToken();
383 SourceLocation LParenLoc = Tok.getLocation();
384 SourceLocation RParenLoc;
385
386 // typeid expressions are always parenthesized.
387 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
388 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000389 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000390
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000391 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000392
393 if (isTypeIdInParens()) {
Douglas Gregor809070a2009-02-18 17:45:20 +0000394 TypeResult Ty = ParseTypeName();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000395
396 // Match the ')'.
397 MatchRHSPunctuation(tok::r_paren, LParenLoc);
398
Douglas Gregor809070a2009-02-18 17:45:20 +0000399 if (Ty.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000400 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000401
402 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Douglas Gregor809070a2009-02-18 17:45:20 +0000403 Ty.get(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000404 } else {
Douglas Gregore0762c92009-06-19 23:52:42 +0000405 // C++0x [expr.typeid]p3:
Mike Stump1eb44332009-09-09 15:08:12 +0000406 // When typeid is applied to an expression other than an lvalue of a
407 // polymorphic class type [...] The expression is an unevaluated
Douglas Gregore0762c92009-06-19 23:52:42 +0000408 // operand (Clause 5).
409 //
Mike Stump1eb44332009-09-09 15:08:12 +0000410 // Note that we can't tell whether the expression is an lvalue of a
Douglas Gregore0762c92009-06-19 23:52:42 +0000411 // polymorphic class type until after we've parsed the expression, so
Douglas Gregorac7610d2009-06-22 20:57:11 +0000412 // we the expression is potentially potentially evaluated.
413 EnterExpressionEvaluationContext Unevaluated(Actions,
414 Action::PotentiallyPotentiallyEvaluated);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000415 Result = ParseExpression();
416
417 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000418 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000419 SkipUntil(tok::r_paren);
420 else {
421 MatchRHSPunctuation(tok::r_paren, LParenLoc);
422
423 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000424 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000425 }
426 }
427
Sebastian Redl20df9b72008-12-11 22:51:44 +0000428 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000429}
430
Reid Spencer5f016e22007-07-11 17:01:13 +0000431/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
432///
433/// boolean-literal: [C++ 2.13.5]
434/// 'true'
435/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000436Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000437 tok::TokenKind Kind = Tok.getKind();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000438 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Reid Spencer5f016e22007-07-11 17:01:13 +0000439}
Chris Lattner50dd2892008-02-26 00:51:44 +0000440
441/// ParseThrowExpression - This handles the C++ throw expression.
442///
443/// throw-expression: [C++ 15]
444/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000445Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000446 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000447 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000448
Chris Lattner2a2819a2008-04-06 06:02:23 +0000449 // If the current token isn't the start of an assignment-expression,
450 // then the expression is not present. This handles things like:
451 // "C ? throw : (void)42", which is crazy but legal.
452 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
453 case tok::semi:
454 case tok::r_paren:
455 case tok::r_square:
456 case tok::r_brace:
457 case tok::colon:
458 case tok::comma:
Sebastian Redlf53597f2009-03-15 17:47:39 +0000459 return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
Chris Lattner50dd2892008-02-26 00:51:44 +0000460
Chris Lattner2a2819a2008-04-06 06:02:23 +0000461 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000462 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000463 if (Expr.isInvalid()) return move(Expr);
Sebastian Redlf53597f2009-03-15 17:47:39 +0000464 return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000465 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000466}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000467
468/// ParseCXXThis - This handles the C++ 'this' pointer.
469///
470/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
471/// a non-lvalue expression whose value is the address of the object for which
472/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000473Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000474 assert(Tok.is(tok::kw_this) && "Not 'this'!");
475 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redlf53597f2009-03-15 17:47:39 +0000476 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000477}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000478
479/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
480/// Can be interpreted either as function-style casting ("int(x)")
481/// or class type construction ("ClassType(x,y,z)")
482/// or creation of a value-initialized type ("int()").
483///
484/// postfix-expression: [C++ 5.2p1]
485/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
486/// typename-specifier '(' expression-list[opt] ')' [TODO]
487///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000488Parser::OwningExprResult
489Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000490 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +0000491 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000492
493 assert(Tok.is(tok::l_paren) && "Expected '('!");
494 SourceLocation LParenLoc = ConsumeParen();
495
Sebastian Redla55e52c2008-11-25 22:21:31 +0000496 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000497 CommaLocsTy CommaLocs;
498
499 if (Tok.isNot(tok::r_paren)) {
500 if (ParseExpressionList(Exprs, CommaLocs)) {
501 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000502 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000503 }
504 }
505
506 // Match the ')'.
507 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
508
Sebastian Redlef0cb8e2009-07-29 13:50:23 +0000509 // TypeRep could be null, if it references an invalid typedef.
510 if (!TypeRep)
511 return ExprError();
512
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000513 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
514 "Unexpected number of commas!");
Sebastian Redlf53597f2009-03-15 17:47:39 +0000515 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
516 LParenLoc, move_arg(Exprs),
Jay Foadbeaaccd2009-05-21 09:52:38 +0000517 CommaLocs.data(), RParenLoc);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000518}
519
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000520/// ParseCXXCondition - if/switch/while/for condition expression.
521///
522/// condition:
523/// expression
524/// type-specifier-seq declarator '=' assignment-expression
525/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
526/// '=' assignment-expression
527///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000528Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000529 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000530 return ParseExpression(); // expression
531
532 SourceLocation StartLoc = Tok.getLocation();
533
534 // type-specifier-seq
535 DeclSpec DS;
536 ParseSpecifierQualifierList(DS);
537
538 // declarator
539 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
540 ParseDeclarator(DeclaratorInfo);
541
542 // simple-asm-expr[opt]
543 if (Tok.is(tok::kw_asm)) {
Sebastian Redlab197ba2009-02-09 18:23:29 +0000544 SourceLocation Loc;
545 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000546 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000547 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000548 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000549 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000550 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Sebastian Redlab197ba2009-02-09 18:23:29 +0000551 DeclaratorInfo.SetRangeEnd(Loc);
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000552 }
553
554 // If attributes are present, parse them.
Sebastian Redlab197ba2009-02-09 18:23:29 +0000555 if (Tok.is(tok::kw___attribute)) {
556 SourceLocation Loc;
557 AttributeList *AttrList = ParseAttributes(&Loc);
558 DeclaratorInfo.AddAttributes(AttrList, Loc);
559 }
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000560
561 // '=' assignment-expression
562 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000563 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000564 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000565 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000566 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000567 return ExprError();
568
Sebastian Redlf53597f2009-03-15 17:47:39 +0000569 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
570 DeclaratorInfo,EqualLoc,
571 move(AssignExpr));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000572}
573
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000574/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
575/// This should only be called when the current token is known to be part of
576/// simple-type-specifier.
577///
578/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000579/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000580/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
581/// char
582/// wchar_t
583/// bool
584/// short
585/// int
586/// long
587/// signed
588/// unsigned
589/// float
590/// double
591/// void
592/// [GNU] typeof-specifier
593/// [C++0x] auto [TODO]
594///
595/// type-name:
596/// class-name
597/// enum-name
598/// typedef-name
599///
600void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
601 DS.SetRangeStart(Tok.getLocation());
602 const char *PrevSpec;
John McCallfec54012009-08-03 20:12:06 +0000603 unsigned DiagID;
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000604 SourceLocation Loc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000605
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000606 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000607 case tok::identifier: // foo::bar
608 case tok::coloncolon: // ::foo::bar
609 assert(0 && "Annotation token should already be formed!");
Mike Stump1eb44332009-09-09 15:08:12 +0000610 default:
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000611 assert(0 && "Not a simple-type-specifier token!");
612 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000613
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000614 // type-name
Chris Lattnerb31757b2009-01-06 05:06:21 +0000615 case tok::annot_typename: {
John McCallfec54012009-08-03 20:12:06 +0000616 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000617 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000618 break;
619 }
Mike Stump1eb44332009-09-09 15:08:12 +0000620
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000621 // builtin types
622 case tok::kw_short:
John McCallfec54012009-08-03 20:12:06 +0000623 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000624 break;
625 case tok::kw_long:
John McCallfec54012009-08-03 20:12:06 +0000626 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000627 break;
628 case tok::kw_signed:
John McCallfec54012009-08-03 20:12:06 +0000629 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000630 break;
631 case tok::kw_unsigned:
John McCallfec54012009-08-03 20:12:06 +0000632 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000633 break;
634 case tok::kw_void:
John McCallfec54012009-08-03 20:12:06 +0000635 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000636 break;
637 case tok::kw_char:
John McCallfec54012009-08-03 20:12:06 +0000638 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000639 break;
640 case tok::kw_int:
John McCallfec54012009-08-03 20:12:06 +0000641 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000642 break;
643 case tok::kw_float:
John McCallfec54012009-08-03 20:12:06 +0000644 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000645 break;
646 case tok::kw_double:
John McCallfec54012009-08-03 20:12:06 +0000647 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000648 break;
649 case tok::kw_wchar_t:
John McCallfec54012009-08-03 20:12:06 +0000650 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000651 break;
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000652 case tok::kw_char16_t:
John McCallfec54012009-08-03 20:12:06 +0000653 DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000654 break;
655 case tok::kw_char32_t:
John McCallfec54012009-08-03 20:12:06 +0000656 DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000657 break;
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000658 case tok::kw_bool:
John McCallfec54012009-08-03 20:12:06 +0000659 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000660 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000661
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000662 // GNU typeof support.
663 case tok::kw_typeof:
664 ParseTypeofSpecifier(DS);
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000665 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000666 return;
667 }
Chris Lattnerb31757b2009-01-06 05:06:21 +0000668 if (Tok.is(tok::annot_typename))
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000669 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
670 else
671 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000672 ConsumeToken();
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000673 DS.Finish(Diags, PP);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000674}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000675
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000676/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
677/// [dcl.name]), which is a non-empty sequence of type-specifiers,
678/// e.g., "const short int". Note that the DeclSpec is *not* finished
679/// by parsing the type-specifier-seq, because these sequences are
680/// typically followed by some form of declarator. Returns true and
681/// emits diagnostics if this is not a type-specifier-seq, false
682/// otherwise.
683///
684/// type-specifier-seq: [C++ 8.1]
685/// type-specifier type-specifier-seq[opt]
686///
687bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
688 DS.SetRangeStart(Tok.getLocation());
689 const char *PrevSpec = 0;
John McCallfec54012009-08-03 20:12:06 +0000690 unsigned DiagID;
691 bool isInvalid = 0;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000692
693 // Parse one or more of the type specifiers.
John McCallfec54012009-08-03 20:12:06 +0000694 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000695 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000696 return true;
697 }
Mike Stump1eb44332009-09-09 15:08:12 +0000698
John McCallfec54012009-08-03 20:12:06 +0000699 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000700
701 return false;
702}
703
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000704/// \brief Finish parsing a C++ unqualified-id that is a template-id of
705/// some form.
706///
707/// This routine is invoked when a '<' is encountered after an identifier or
708/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
709/// whether the unqualified-id is actually a template-id. This routine will
710/// then parse the template arguments and form the appropriate template-id to
711/// return to the caller.
712///
713/// \param SS the nested-name-specifier that precedes this template-id, if
714/// we're actually parsing a qualified-id.
715///
716/// \param Name for constructor and destructor names, this is the actual
717/// identifier that may be a template-name.
718///
719/// \param NameLoc the location of the class-name in a constructor or
720/// destructor.
721///
722/// \param EnteringContext whether we're entering the scope of the
723/// nested-name-specifier.
724///
Douglas Gregor46df8cc2009-11-03 21:24:04 +0000725/// \param ObjectType if this unqualified-id occurs within a member access
726/// expression, the type of the base object whose member is being accessed.
727///
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000728/// \param Id as input, describes the template-name or operator-function-id
729/// that precedes the '<'. If template arguments were parsed successfully,
730/// will be updated with the template-id.
731///
732/// \returns true if a parse error occurred, false otherwise.
733bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
734 IdentifierInfo *Name,
735 SourceLocation NameLoc,
736 bool EnteringContext,
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000737 TypeTy *ObjectType,
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000738 UnqualifiedId &Id) {
739 assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
740
741 TemplateTy Template;
742 TemplateNameKind TNK = TNK_Non_template;
743 switch (Id.getKind()) {
744 case UnqualifiedId::IK_Identifier:
Douglas Gregor014e88d2009-11-03 23:16:33 +0000745 case UnqualifiedId::IK_OperatorFunctionId:
746 TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext,
747 Template);
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000748 break;
749
Douglas Gregor014e88d2009-11-03 23:16:33 +0000750 case UnqualifiedId::IK_ConstructorName: {
751 UnqualifiedId TemplateName;
752 TemplateName.setIdentifier(Name, NameLoc);
753 TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
754 EnteringContext, Template);
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000755 break;
756 }
757
Douglas Gregor014e88d2009-11-03 23:16:33 +0000758 case UnqualifiedId::IK_DestructorName: {
759 UnqualifiedId TemplateName;
760 TemplateName.setIdentifier(Name, NameLoc);
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000761 if (ObjectType) {
Douglas Gregor014e88d2009-11-03 23:16:33 +0000762 Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
763 TemplateName, ObjectType);
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000764 TNK = TNK_Dependent_template_name;
765 if (!Template.get())
766 return true;
767 } else {
Douglas Gregor014e88d2009-11-03 23:16:33 +0000768 TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000769 EnteringContext, Template);
770
771 if (TNK == TNK_Non_template && Id.DestructorName == 0) {
772 // The identifier following the destructor did not refer to a template
773 // or to a type. Complain.
774 if (ObjectType)
775 Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
776 << Name;
777 else
778 Diag(NameLoc, diag::err_destructor_class_name);
779 return true;
780 }
781 }
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000782 break;
Douglas Gregor014e88d2009-11-03 23:16:33 +0000783 }
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000784
785 default:
786 return false;
787 }
788
789 if (TNK == TNK_Non_template)
790 return false;
791
792 // Parse the enclosed template argument list.
793 SourceLocation LAngleLoc, RAngleLoc;
794 TemplateArgList TemplateArgs;
795 TemplateArgIsTypeList TemplateArgIsType;
796 TemplateArgLocationList TemplateArgLocations;
797 if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
798 &SS, true, LAngleLoc,
799 TemplateArgs,
800 TemplateArgIsType,
801 TemplateArgLocations,
802 RAngleLoc))
803 return true;
804
805 if (Id.getKind() == UnqualifiedId::IK_Identifier ||
806 Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) {
807 // Form a parsed representation of the template-id to be stored in the
808 // UnqualifiedId.
809 TemplateIdAnnotation *TemplateId
810 = TemplateIdAnnotation::Allocate(TemplateArgs.size());
811
812 if (Id.getKind() == UnqualifiedId::IK_Identifier) {
813 TemplateId->Name = Id.Identifier;
Douglas Gregor014e88d2009-11-03 23:16:33 +0000814 TemplateId->Operator = OO_None;
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000815 TemplateId->TemplateNameLoc = Id.StartLocation;
816 } else {
Douglas Gregor014e88d2009-11-03 23:16:33 +0000817 TemplateId->Name = 0;
818 TemplateId->Operator = Id.OperatorFunctionId.Operator;
819 TemplateId->TemplateNameLoc = Id.StartLocation;
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000820 }
821
822 TemplateId->Template = Template.getAs<void*>();
823 TemplateId->Kind = TNK;
824 TemplateId->LAngleLoc = LAngleLoc;
825 TemplateId->RAngleLoc = RAngleLoc;
826 void **Args = TemplateId->getTemplateArgs();
827 bool *ArgIsType = TemplateId->getTemplateArgIsType();
828 SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
829 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
830 Arg != ArgEnd; ++Arg) {
831 Args[Arg] = TemplateArgs[Arg];
832 ArgIsType[Arg] = TemplateArgIsType[Arg];
833 ArgLocs[Arg] = TemplateArgLocations[Arg];
834 }
835
836 Id.setTemplateId(TemplateId);
837 return false;
838 }
839
840 // Bundle the template arguments together.
841 ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
842 TemplateArgIsType.data(),
843 TemplateArgs.size());
844
845 // Constructor and destructor names.
846 Action::TypeResult Type
847 = Actions.ActOnTemplateIdType(Template, NameLoc,
848 LAngleLoc, TemplateArgsPtr,
849 &TemplateArgLocations[0],
850 RAngleLoc);
851 if (Type.isInvalid())
852 return true;
853
854 if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
855 Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
856 else
857 Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
858
859 return false;
860}
861
862/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
863/// name of an entity.
864///
865/// \code
866/// unqualified-id: [C++ expr.prim.general]
867/// identifier
868/// operator-function-id
869/// conversion-function-id
870/// [C++0x] literal-operator-id [TODO]
871/// ~ class-name
872/// template-id
873///
874/// operator-function-id: [C++ 13.5]
875/// 'operator' operator
876///
877/// operator: one of
878/// new delete new[] delete[]
879/// + - * / % ^ & | ~
880/// ! = < > += -= *= /= %=
881/// ^= &= |= << >> >>= <<= == !=
882/// <= >= && || ++ -- , ->* ->
883/// () []
884///
885/// conversion-function-id: [C++ 12.3.2]
886/// operator conversion-type-id
887///
888/// conversion-type-id:
889/// type-specifier-seq conversion-declarator[opt]
890///
891/// conversion-declarator:
892/// ptr-operator conversion-declarator[opt]
893/// \endcode
894///
895/// \param The nested-name-specifier that preceded this unqualified-id. If
896/// non-empty, then we are parsing the unqualified-id of a qualified-id.
897///
898/// \param EnteringContext whether we are entering the scope of the
899/// nested-name-specifier.
900///
901/// \param AllowDestructorName whether we allow parsing of a destructor name.
902///
903/// \param AllowConstructorName whether we allow parsing a constructor name.
904///
Douglas Gregor46df8cc2009-11-03 21:24:04 +0000905/// \param ObjectType if this unqualified-id occurs within a member access
906/// expression, the type of the base object whose member is being accessed.
907///
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000908/// \param Result on a successful parse, contains the parsed unqualified-id.
909///
910/// \returns true if parsing fails, false otherwise.
911bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
912 bool AllowDestructorName,
913 bool AllowConstructorName,
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000914 TypeTy *ObjectType,
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000915 UnqualifiedId &Result) {
916 // unqualified-id:
917 // identifier
918 // template-id (when it hasn't already been annotated)
919 if (Tok.is(tok::identifier)) {
920 // Consume the identifier.
921 IdentifierInfo *Id = Tok.getIdentifierInfo();
922 SourceLocation IdLoc = ConsumeToken();
923
924 if (AllowConstructorName &&
925 Actions.isCurrentClassName(*Id, CurScope, &SS)) {
926 // We have parsed a constructor name.
927 Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
928 &SS, false),
929 IdLoc, IdLoc);
930 } else {
931 // We have parsed an identifier.
932 Result.setIdentifier(Id, IdLoc);
933 }
934
935 // If the next token is a '<', we may have a template.
936 if (Tok.is(tok::less))
937 return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
Douglas Gregor2d1c2142009-11-03 19:44:04 +0000938 ObjectType, Result);
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000939
940 return false;
941 }
942
943 // unqualified-id:
944 // template-id (already parsed and annotated)
945 if (Tok.is(tok::annot_template_id)) {
946 // FIXME: Could this be a constructor name???
947
948 // We have already parsed a template-id; consume the annotation token as
949 // our unqualified-id.
950 Result.setTemplateId(
951 static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue()));
952 ConsumeToken();
953 return false;
954 }
955
956 // unqualified-id:
957 // operator-function-id
958 // conversion-function-id
959 if (Tok.is(tok::kw_operator)) {
960 // Consume the 'operator' keyword.
961 SourceLocation KeywordLoc = ConsumeToken();
962
963 // Determine what kind of operator name we have.
964 unsigned SymbolIdx = 0;
965 SourceLocation SymbolLocations[3];
966 OverloadedOperatorKind Op = OO_None;
967 switch (Tok.getKind()) {
968 case tok::kw_new:
969 case tok::kw_delete: {
970 bool isNew = Tok.getKind() == tok::kw_new;
971 // Consume the 'new' or 'delete'.
972 SymbolLocations[SymbolIdx++] = ConsumeToken();
973 if (Tok.is(tok::l_square)) {
974 // Consume the '['.
975 SourceLocation LBracketLoc = ConsumeBracket();
976 // Consume the ']'.
977 SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
978 LBracketLoc);
979 if (RBracketLoc.isInvalid())
980 return true;
981
982 SymbolLocations[SymbolIdx++] = LBracketLoc;
983 SymbolLocations[SymbolIdx++] = RBracketLoc;
984 Op = isNew? OO_Array_New : OO_Array_Delete;
985 } else {
986 Op = isNew? OO_New : OO_Delete;
987 }
988 break;
989 }
990
991 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
992 case tok::Token: \
993 SymbolLocations[SymbolIdx++] = ConsumeToken(); \
994 Op = OO_##Name; \
995 break;
996 #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
997 #include "clang/Basic/OperatorKinds.def"
998
999 case tok::l_paren: {
1000 // Consume the '('.
1001 SourceLocation LParenLoc = ConsumeParen();
1002 // Consume the ')'.
1003 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
1004 LParenLoc);
1005 if (RParenLoc.isInvalid())
1006 return true;
1007
1008 SymbolLocations[SymbolIdx++] = LParenLoc;
1009 SymbolLocations[SymbolIdx++] = RParenLoc;
1010 Op = OO_Call;
1011 break;
1012 }
1013
1014 case tok::l_square: {
1015 // Consume the '['.
1016 SourceLocation LBracketLoc = ConsumeBracket();
1017 // Consume the ']'.
1018 SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
1019 LBracketLoc);
1020 if (RBracketLoc.isInvalid())
1021 return true;
1022
1023 SymbolLocations[SymbolIdx++] = LBracketLoc;
1024 SymbolLocations[SymbolIdx++] = RBracketLoc;
1025 Op = OO_Subscript;
1026 break;
1027 }
1028
1029 case tok::code_completion: {
1030 // Code completion for the operator name.
1031 Actions.CodeCompleteOperatorName(CurScope);
1032
1033 // Consume the operator token.
1034 ConsumeToken();
1035
1036 // Don't try to parse any further.
1037 return true;
1038 }
1039
1040 default:
1041 break;
1042 }
1043
1044 if (Op != OO_None) {
1045 // We have parsed an operator-function-id.
1046 Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
1047
1048 // If the next token is a '<', we may have a template.
1049 if (Tok.is(tok::less))
1050 return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
Douglas Gregor2d1c2142009-11-03 19:44:04 +00001051 EnteringContext, ObjectType,
1052 Result);
Douglas Gregor3f9a0562009-11-03 01:35:08 +00001053
1054 return false;
1055 }
1056
1057 // Parse a conversion-function-id.
1058 //
1059 // conversion-function-id: [C++ 12.3.2]
1060 // operator conversion-type-id
1061 //
1062 // conversion-type-id:
1063 // type-specifier-seq conversion-declarator[opt]
1064 //
1065 // conversion-declarator:
1066 // ptr-operator conversion-declarator[opt]
1067
1068 // Parse the type-specifier-seq.
1069 DeclSpec DS;
1070 if (ParseCXXTypeSpecifierSeq(DS))
1071 return true;
1072
1073 // Parse the conversion-declarator, which is merely a sequence of
1074 // ptr-operators.
1075 Declarator D(DS, Declarator::TypeNameContext);
1076 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
1077
1078 // Finish up the type.
1079 Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
1080 if (Ty.isInvalid())
1081 return true;
1082
1083 // Note that this is a conversion-function-id.
1084 Result.setConversionFunctionId(KeywordLoc, Ty.get(),
1085 D.getSourceRange().getEnd());
1086 return false;
1087 }
1088
1089 if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
1090 // C++ [expr.unary.op]p10:
1091 // There is an ambiguity in the unary-expression ~X(), where X is a
1092 // class-name. The ambiguity is resolved in favor of treating ~ as a
1093 // unary complement rather than treating ~X as referring to a destructor.
1094
1095 // Parse the '~'.
1096 SourceLocation TildeLoc = ConsumeToken();
1097
1098 // Parse the class-name.
1099 if (Tok.isNot(tok::identifier)) {
1100 Diag(Tok, diag::err_destructor_class_name);
1101 return true;
1102 }
1103
1104 // Parse the class-name (or template-name in a simple-template-id).
1105 IdentifierInfo *ClassName = Tok.getIdentifierInfo();
1106 SourceLocation ClassNameLoc = ConsumeToken();
1107
Douglas Gregor2d1c2142009-11-03 19:44:04 +00001108 if (Tok.is(tok::less)) {
1109 Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
1110 return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
1111 EnteringContext, ObjectType, Result);
1112 }
1113
Douglas Gregor3f9a0562009-11-03 01:35:08 +00001114 // Note that this is a destructor name.
1115 Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
1116 CurScope, &SS);
1117 if (!Ty) {
Douglas Gregor2d1c2142009-11-03 19:44:04 +00001118 if (ObjectType)
1119 Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
1120 << ClassName;
1121 else
1122 Diag(ClassNameLoc, diag::err_destructor_class_name);
Douglas Gregor3f9a0562009-11-03 01:35:08 +00001123 return true;
1124 }
1125
1126 Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
Douglas Gregor3f9a0562009-11-03 01:35:08 +00001127 return false;
1128 }
1129
Douglas Gregor2d1c2142009-11-03 19:44:04 +00001130 Diag(Tok, diag::err_expected_unqualified_id)
1131 << getLang().CPlusPlus;
Douglas Gregor3f9a0562009-11-03 01:35:08 +00001132 return true;
1133}
1134
Douglas Gregor43c7bad2008-11-17 16:14:12 +00001135/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001136/// operator name (C++ [over.oper]). If successful, returns the
1137/// predefined identifier that corresponds to that overloaded
1138/// operator. Otherwise, returns NULL and does not consume any tokens.
1139///
1140/// operator-function-id: [C++ 13.5]
1141/// 'operator' operator
1142///
1143/// operator: one of
1144/// new delete new[] delete[]
1145/// + - * / % ^ & | ~
1146/// ! = < > += -= *= /= %=
1147/// ^= &= |= << >> >>= <<= == !=
1148/// <= >= && || ++ -- , ->* ->
1149/// () []
Sebastian Redlab197ba2009-02-09 18:23:29 +00001150OverloadedOperatorKind
1151Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +00001152 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Sebastian Redlab197ba2009-02-09 18:23:29 +00001153 SourceLocation Loc;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001154
1155 OverloadedOperatorKind Op = OO_None;
1156 switch (NextToken().getKind()) {
1157 case tok::kw_new:
1158 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +00001159 Loc = ConsumeToken(); // 'new'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001160 if (Tok.is(tok::l_square)) {
1161 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +00001162 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001163 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
1164 Op = OO_Array_New;
1165 } else {
1166 Op = OO_New;
1167 }
Sebastian Redlab197ba2009-02-09 18:23:29 +00001168 if (EndLoc)
1169 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +00001170 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001171
1172 case tok::kw_delete:
1173 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +00001174 Loc = ConsumeToken(); // 'delete'
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001175 if (Tok.is(tok::l_square)) {
1176 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +00001177 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001178 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
1179 Op = OO_Array_Delete;
1180 } else {
1181 Op = OO_Delete;
1182 }
Sebastian Redlab197ba2009-02-09 18:23:29 +00001183 if (EndLoc)
1184 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +00001185 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001186
Douglas Gregor02bcd4c2008-11-10 13:38:07 +00001187#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001188 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +00001189#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001190#include "clang/Basic/OperatorKinds.def"
1191
1192 case tok::l_paren:
1193 ConsumeToken(); // 'operator'
1194 ConsumeParen(); // '('
Sebastian Redlab197ba2009-02-09 18:23:29 +00001195 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001196 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Sebastian Redlab197ba2009-02-09 18:23:29 +00001197 if (EndLoc)
1198 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +00001199 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001200
1201 case tok::l_square:
1202 ConsumeToken(); // 'operator'
1203 ConsumeBracket(); // '['
Sebastian Redlab197ba2009-02-09 18:23:29 +00001204 Loc = Tok.getLocation();
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001205 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Sebastian Redlab197ba2009-02-09 18:23:29 +00001206 if (EndLoc)
1207 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +00001208 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001209
Douglas Gregored8d3222009-09-18 20:05:18 +00001210 case tok::code_completion: {
1211 // Code completion for the operator name.
1212 Actions.CodeCompleteOperatorName(CurScope);
1213
1214 // Consume the 'operator' token, then replace the code-completion token
1215 // with an 'operator' token and try again.
1216 SourceLocation OperatorLoc = ConsumeToken();
1217 Tok.setLocation(OperatorLoc);
1218 Tok.setKind(tok::kw_operator);
1219 return TryParseOperatorFunctionId(EndLoc);
1220 }
1221
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001222 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +00001223 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001224 }
1225
Douglas Gregor43c7bad2008-11-17 16:14:12 +00001226 ConsumeToken(); // 'operator'
Sebastian Redlab197ba2009-02-09 18:23:29 +00001227 Loc = ConsumeAnyToken(); // the operator itself
1228 if (EndLoc)
1229 *EndLoc = Loc;
Douglas Gregore94ca9e42008-11-18 14:39:36 +00001230 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +00001231}
Douglas Gregor2f1bc522008-11-07 20:08:42 +00001232
1233/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
1234/// which expresses the name of a user-defined conversion operator
1235/// (C++ [class.conv.fct]p1). Returns the type that this operator is
1236/// specifying a conversion for, or NULL if there was an error.
1237///
1238/// conversion-function-id: [C++ 12.3.2]
1239/// operator conversion-type-id
1240///
1241/// conversion-type-id:
1242/// type-specifier-seq conversion-declarator[opt]
1243///
1244/// conversion-declarator:
1245/// ptr-operator conversion-declarator[opt]
Sebastian Redlab197ba2009-02-09 18:23:29 +00001246Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
Douglas Gregor2f1bc522008-11-07 20:08:42 +00001247 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
1248 ConsumeToken(); // 'operator'
1249
1250 // Parse the type-specifier-seq.
1251 DeclSpec DS;
1252 if (ParseCXXTypeSpecifierSeq(DS))
1253 return 0;
1254
1255 // Parse the conversion-declarator, which is merely a sequence of
1256 // ptr-operators.
1257 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001258 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Sebastian Redlab197ba2009-02-09 18:23:29 +00001259 if (EndLoc)
1260 *EndLoc = D.getSourceRange().getEnd();
Douglas Gregor2f1bc522008-11-07 20:08:42 +00001261
1262 // Finish up the type.
1263 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
Douglas Gregor5ac8aff2009-01-26 22:44:13 +00001264 if (Result.isInvalid())
Douglas Gregor2f1bc522008-11-07 20:08:42 +00001265 return 0;
1266 else
Douglas Gregor5ac8aff2009-01-26 22:44:13 +00001267 return Result.get();
Douglas Gregor2f1bc522008-11-07 20:08:42 +00001268}
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001269
1270/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
1271/// memory in a typesafe manner and call constructors.
Mike Stump1eb44332009-09-09 15:08:12 +00001272///
Chris Lattner59232d32009-01-04 21:25:24 +00001273/// This method is called to parse the new expression after the optional :: has
1274/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
1275/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001276///
1277/// new-expression:
1278/// '::'[opt] 'new' new-placement[opt] new-type-id
1279/// new-initializer[opt]
1280/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
1281/// new-initializer[opt]
1282///
1283/// new-placement:
1284/// '(' expression-list ')'
1285///
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001286/// new-type-id:
1287/// type-specifier-seq new-declarator[opt]
1288///
1289/// new-declarator:
1290/// ptr-operator new-declarator[opt]
1291/// direct-new-declarator
1292///
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001293/// new-initializer:
1294/// '(' expression-list[opt] ')'
1295/// [C++0x] braced-init-list [TODO]
1296///
Chris Lattner59232d32009-01-04 21:25:24 +00001297Parser::OwningExprResult
1298Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
1299 assert(Tok.is(tok::kw_new) && "expected 'new' token");
1300 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001301
1302 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
1303 // second form of new-expression. It can't be a new-type-id.
1304
Sebastian Redla55e52c2008-11-25 22:21:31 +00001305 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001306 SourceLocation PlacementLParen, PlacementRParen;
1307
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001308 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001309 DeclSpec DS;
1310 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001311 if (Tok.is(tok::l_paren)) {
1312 // If it turns out to be a placement, we change the type location.
1313 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001314 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
1315 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +00001316 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001317 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001318
1319 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001320 if (PlacementRParen.isInvalid()) {
1321 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +00001322 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001323 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001324
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001325 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001326 // Reset the placement locations. There was no placement.
1327 PlacementLParen = PlacementRParen = SourceLocation();
1328 ParenTypeId = true;
1329 } else {
1330 // We still need the type.
1331 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001332 SourceLocation LParen = ConsumeParen();
1333 ParseSpecifierQualifierList(DS);
Sebastian Redlab197ba2009-02-09 18:23:29 +00001334 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001335 ParseDeclarator(DeclaratorInfo);
1336 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001337 ParenTypeId = true;
1338 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001339 if (ParseCXXTypeSpecifierSeq(DS))
1340 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +00001341 else {
1342 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001343 ParseDeclaratorInternal(DeclaratorInfo,
1344 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +00001345 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001346 ParenTypeId = false;
1347 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001348 }
1349 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001350 // A new-type-id is a simplified type-id, where essentially the
1351 // direct-declarator is replaced by a direct-new-declarator.
1352 if (ParseCXXTypeSpecifierSeq(DS))
1353 DeclaratorInfo.setInvalidType(true);
Sebastian Redlab197ba2009-02-09 18:23:29 +00001354 else {
1355 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001356 ParseDeclaratorInternal(DeclaratorInfo,
1357 &Parser::ParseDirectNewDeclarator);
Sebastian Redlab197ba2009-02-09 18:23:29 +00001358 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001359 ParenTypeId = false;
1360 }
Chris Lattnereaaebc72009-04-25 08:06:05 +00001361 if (DeclaratorInfo.isInvalidType()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001362 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +00001363 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001364 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001365
Sebastian Redla55e52c2008-11-25 22:21:31 +00001366 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001367 SourceLocation ConstructorLParen, ConstructorRParen;
1368
1369 if (Tok.is(tok::l_paren)) {
1370 ConstructorLParen = ConsumeParen();
1371 if (Tok.isNot(tok::r_paren)) {
1372 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001373 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
1374 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +00001375 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001376 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001377 }
1378 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001379 if (ConstructorRParen.isInvalid()) {
1380 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +00001381 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001382 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001383 }
1384
Sebastian Redlf53597f2009-03-15 17:47:39 +00001385 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
1386 move_arg(PlacementArgs), PlacementRParen,
1387 ParenTypeId, DeclaratorInfo, ConstructorLParen,
1388 move_arg(ConstructorArgs), ConstructorRParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001389}
1390
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001391/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
1392/// passed to ParseDeclaratorInternal.
1393///
1394/// direct-new-declarator:
1395/// '[' expression ']'
1396/// direct-new-declarator '[' constant-expression ']'
1397///
Chris Lattner59232d32009-01-04 21:25:24 +00001398void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001399 // Parse the array dimensions.
1400 bool first = true;
1401 while (Tok.is(tok::l_square)) {
1402 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +00001403 OwningExprResult Size(first ? ParseExpression()
1404 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +00001405 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001406 // Recover
1407 SkipUntil(tok::r_square);
1408 return;
1409 }
1410 first = false;
1411
Sebastian Redlab197ba2009-02-09 18:23:29 +00001412 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001413 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001414 Size.release(), LLoc, RLoc),
Sebastian Redlab197ba2009-02-09 18:23:29 +00001415 RLoc);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001416
Sebastian Redlab197ba2009-02-09 18:23:29 +00001417 if (RLoc.isInvalid())
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001418 return;
1419 }
1420}
1421
1422/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
1423/// This ambiguity appears in the syntax of the C++ new operator.
1424///
1425/// new-expression:
1426/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
1427/// new-initializer[opt]
1428///
1429/// new-placement:
1430/// '(' expression-list ')'
1431///
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001432bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +00001433 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001434 // The '(' was already consumed.
1435 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001436 ParseSpecifierQualifierList(D.getMutableDeclSpec());
Sebastian Redlab197ba2009-02-09 18:23:29 +00001437 D.SetSourceRange(D.getDeclSpec().getSourceRange());
Sebastian Redlcee63fb2008-12-02 14:43:59 +00001438 ParseDeclarator(D);
Chris Lattnereaaebc72009-04-25 08:06:05 +00001439 return D.isInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001440 }
1441
1442 // It's not a type, it has to be an expression list.
1443 // Discard the comma locations - ActOnCXXNew has enough parameters.
1444 CommaLocsTy CommaLocs;
1445 return ParseExpressionList(PlacementArgs, CommaLocs);
1446}
1447
1448/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
1449/// to free memory allocated by new.
1450///
Chris Lattner59232d32009-01-04 21:25:24 +00001451/// This method is called to parse the 'delete' expression after the optional
1452/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
1453/// and "Start" is its location. Otherwise, "Start" is the location of the
1454/// 'delete' token.
1455///
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001456/// delete-expression:
1457/// '::'[opt] 'delete' cast-expression
1458/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +00001459Parser::OwningExprResult
1460Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
1461 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
1462 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001463
1464 // Array delete?
1465 bool ArrayDelete = false;
1466 if (Tok.is(tok::l_square)) {
1467 ArrayDelete = true;
1468 SourceLocation LHS = ConsumeBracket();
1469 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
1470 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +00001471 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001472 }
1473
Sebastian Redl2f7ece72008-12-11 21:36:32 +00001474 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +00001475 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +00001476 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001477
Sebastian Redlf53597f2009-03-15 17:47:39 +00001478 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
Sebastian Redl4c5d3202008-11-21 19:14:01 +00001479}
Sebastian Redl64b45f72009-01-05 20:52:13 +00001480
Mike Stump1eb44332009-09-09 15:08:12 +00001481static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
Sebastian Redl64b45f72009-01-05 20:52:13 +00001482 switch(kind) {
1483 default: assert(false && "Not a known unary type trait.");
1484 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
1485 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
1486 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
1487 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
1488 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
1489 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
1490 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
1491 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
1492 case tok::kw___is_abstract: return UTT_IsAbstract;
1493 case tok::kw___is_class: return UTT_IsClass;
1494 case tok::kw___is_empty: return UTT_IsEmpty;
1495 case tok::kw___is_enum: return UTT_IsEnum;
1496 case tok::kw___is_pod: return UTT_IsPOD;
1497 case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
1498 case tok::kw___is_union: return UTT_IsUnion;
1499 }
1500}
1501
1502/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
1503/// pseudo-functions that allow implementation of the TR1/C++0x type traits
1504/// templates.
1505///
1506/// primary-expression:
1507/// [GNU] unary-type-trait '(' type-id ')'
1508///
Mike Stump1eb44332009-09-09 15:08:12 +00001509Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
Sebastian Redl64b45f72009-01-05 20:52:13 +00001510 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
1511 SourceLocation Loc = ConsumeToken();
1512
1513 SourceLocation LParen = Tok.getLocation();
1514 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1515 return ExprError();
1516
1517 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
1518 // there will be cryptic errors about mismatched parentheses and missing
1519 // specifiers.
Douglas Gregor809070a2009-02-18 17:45:20 +00001520 TypeResult Ty = ParseTypeName();
Sebastian Redl64b45f72009-01-05 20:52:13 +00001521
1522 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
1523
Douglas Gregor809070a2009-02-18 17:45:20 +00001524 if (Ty.isInvalid())
1525 return ExprError();
1526
1527 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
Sebastian Redl64b45f72009-01-05 20:52:13 +00001528}
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001529
1530/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
1531/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
1532/// based on the context past the parens.
1533Parser::OwningExprResult
1534Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
1535 TypeTy *&CastTy,
1536 SourceLocation LParenLoc,
1537 SourceLocation &RParenLoc) {
1538 assert(getLang().CPlusPlus && "Should only be called for C++!");
1539 assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
1540 assert(isTypeIdInParens() && "Not a type-id!");
1541
1542 OwningExprResult Result(Actions, true);
1543 CastTy = 0;
1544
1545 // We need to disambiguate a very ugly part of the C++ syntax:
1546 //
1547 // (T())x; - type-id
1548 // (T())*x; - type-id
1549 // (T())/x; - expression
1550 // (T()); - expression
1551 //
1552 // The bad news is that we cannot use the specialized tentative parser, since
1553 // it can only verify that the thing inside the parens can be parsed as
1554 // type-id, it is not useful for determining the context past the parens.
1555 //
1556 // The good news is that the parser can disambiguate this part without
Argyrios Kyrtzidisa558a892009-05-22 15:12:46 +00001557 // making any unnecessary Action calls.
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001558 //
1559 // It uses a scheme similar to parsing inline methods. The parenthesized
1560 // tokens are cached, the context that follows is determined (possibly by
1561 // parsing a cast-expression), and then we re-introduce the cached tokens
1562 // into the token stream and parse them appropriately.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001563
Mike Stump1eb44332009-09-09 15:08:12 +00001564 ParenParseOption ParseAs;
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001565 CachedTokens Toks;
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001566
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001567 // Store the tokens of the parentheses. We will parse them after we determine
1568 // the context that follows them.
1569 if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
1570 // We didn't find the ')' we expected.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001571 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1572 return ExprError();
1573 }
1574
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001575 if (Tok.is(tok::l_brace)) {
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001576 ParseAs = CompoundLiteral;
1577 } else {
1578 bool NotCastExpr;
Eli Friedmanb53f08a2009-05-25 19:41:42 +00001579 // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
1580 if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
1581 NotCastExpr = true;
1582 } else {
1583 // Try parsing the cast-expression that may follow.
1584 // If it is not a cast-expression, NotCastExpr will be true and no token
1585 // will be consumed.
1586 Result = ParseCastExpression(false/*isUnaryExpression*/,
1587 false/*isAddressofOperand*/,
Nate Begeman2ef13e52009-08-10 23:49:36 +00001588 NotCastExpr, false);
Eli Friedmanb53f08a2009-05-25 19:41:42 +00001589 }
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001590
1591 // If we parsed a cast-expression, it's really a type-id, otherwise it's
1592 // an expression.
1593 ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001594 }
1595
Mike Stump1eb44332009-09-09 15:08:12 +00001596 // The current token should go after the cached tokens.
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001597 Toks.push_back(Tok);
1598 // Re-enter the stored parenthesized tokens into the token stream, so we may
1599 // parse them now.
1600 PP.EnterTokenStream(Toks.data(), Toks.size(),
1601 true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
1602 // Drop the current token and bring the first cached one. It's the same token
1603 // as when we entered this function.
1604 ConsumeAnyToken();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001605
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001606 if (ParseAs >= CompoundLiteral) {
1607 TypeResult Ty = ParseTypeName();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001608
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001609 // Match the ')'.
1610 if (Tok.is(tok::r_paren))
1611 RParenLoc = ConsumeParen();
1612 else
1613 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001614
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001615 if (ParseAs == CompoundLiteral) {
1616 ExprType = CompoundLiteral;
1617 return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
1618 }
Mike Stump1eb44332009-09-09 15:08:12 +00001619
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001620 // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
1621 assert(ParseAs == CastExpr);
1622
1623 if (Ty.isInvalid())
1624 return ExprError();
1625
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001626 CastTy = Ty.get();
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001627
1628 // Result is what ParseCastExpression returned earlier.
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001629 if (!Result.isInvalid())
Mike Stump1eb44332009-09-09 15:08:12 +00001630 Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
Nate Begeman2ef13e52009-08-10 23:49:36 +00001631 move(Result));
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001632 return move(Result);
1633 }
Mike Stump1eb44332009-09-09 15:08:12 +00001634
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001635 // Not a compound literal, and not followed by a cast-expression.
1636 assert(ParseAs == SimpleExpr);
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001637
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001638 ExprType = SimpleExpr;
Argyrios Kyrtzidisf40882a2009-05-22 21:09:47 +00001639 Result = ParseExpression();
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001640 if (!Result.isInvalid() && Tok.is(tok::r_paren))
1641 Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
1642
1643 // Match the ')'.
1644 if (Result.isInvalid()) {
1645 SkipUntil(tok::r_paren);
1646 return ExprError();
1647 }
Mike Stump1eb44332009-09-09 15:08:12 +00001648
Argyrios Kyrtzidisf58f45e2009-05-22 10:24:42 +00001649 if (Tok.is(tok::r_paren))
1650 RParenLoc = ConsumeParen();
1651 else
1652 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1653
1654 return move(Result);
1655}