blob: fa651569f8e16f8166b0406e0f5b6d53ec9959cb [file] [log] [blame]
Chris Lattner29375652006-12-04 18:06:35 +00001//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner5b12ab82007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattner29375652006-12-04 18:06:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Expression parsing implementation for C++.
11//
12//===----------------------------------------------------------------------===//
13
Chris Lattner60f36222009-01-29 05:15:15 +000014#include "clang/Parse/ParseDiagnostic.h"
Chris Lattner29375652006-12-04 18:06:35 +000015#include "clang/Parse/Parser.h"
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +000016#include "clang/Parse/DeclSpec.h"
Chris Lattner29375652006-12-04 18:06:35 +000017using namespace clang;
18
Mike Stump11289f42009-09-09 15:08:12 +000019/// \brief Parse global scope or nested-name-specifier if present.
Douglas Gregorb7bfe792009-09-02 22:59:36 +000020///
21/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
Mike Stump11289f42009-09-09 15:08:12 +000022/// may be preceded by '::'). Note that this routine will not parse ::new or
Douglas Gregorb7bfe792009-09-02 22:59:36 +000023/// ::delete; it will just leave them in the token stream.
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +000024///
25/// '::'[opt] nested-name-specifier
26/// '::'
27///
28/// nested-name-specifier:
29/// type-name '::'
30/// namespace-name '::'
31/// nested-name-specifier identifier '::'
Douglas Gregorb7bfe792009-09-02 22:59:36 +000032/// nested-name-specifier 'template'[opt] simple-template-id '::'
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +000033///
Douglas Gregorb7bfe792009-09-02 22:59:36 +000034///
Mike Stump11289f42009-09-09 15:08:12 +000035/// \param SS the scope specifier that will be set to the parsed
Douglas Gregorb7bfe792009-09-02 22:59:36 +000036/// nested-name-specifier (or empty)
37///
Mike Stump11289f42009-09-09 15:08:12 +000038/// \param ObjectType if this nested-name-specifier is being parsed following
Douglas Gregorb7bfe792009-09-02 22:59:36 +000039/// the "." or "->" of a member access expression, this parameter provides the
40/// type of the object whose members are being accessed.
41///
42/// \param EnteringContext whether we will be entering into the context of
43/// the nested-name-specifier after parsing it.
44///
45/// \returns true if a scope specifier was parsed.
Douglas Gregore861bac2009-08-25 22:51:20 +000046bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Douglas Gregorb7bfe792009-09-02 22:59:36 +000047 Action::TypeTy *ObjectType,
Douglas Gregore861bac2009-08-25 22:51:20 +000048 bool EnteringContext) {
Argyrios Kyrtzidisace521a2008-11-26 21:41:52 +000049 assert(getLang().CPlusPlus &&
Chris Lattnerb5134c02009-01-05 01:24:05 +000050 "Call sites of this function should be guarded by checking for C++");
Mike Stump11289f42009-09-09 15:08:12 +000051
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +000052 if (Tok.is(tok::annot_cxxscope)) {
Douglas Gregorc23500e2009-03-26 23:56:24 +000053 SS.setScopeRep(Tok.getAnnotationValue());
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +000054 SS.setRange(Tok.getAnnotationRange());
55 ConsumeToken();
Argyrios Kyrtzidisace521a2008-11-26 21:41:52 +000056 return true;
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +000057 }
Chris Lattnerf9b2cd42009-01-04 21:14:15 +000058
Douglas Gregor7f741122009-02-25 19:37:18 +000059 bool HasScopeSpecifier = false;
60
Chris Lattner8a7d10d2009-01-05 03:55:46 +000061 if (Tok.is(tok::coloncolon)) {
62 // ::new and ::delete aren't nested-name-specifiers.
63 tok::TokenKind NextKind = NextToken().getKind();
64 if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
65 return false;
Mike Stump11289f42009-09-09 15:08:12 +000066
Chris Lattner45ddec32009-01-05 00:13:00 +000067 // '::' - Global scope qualifier.
Chris Lattner6b87b9d2009-01-05 02:07:19 +000068 SourceLocation CCLoc = ConsumeToken();
Chris Lattner6b87b9d2009-01-05 02:07:19 +000069 SS.setBeginLoc(CCLoc);
Douglas Gregorc23500e2009-03-26 23:56:24 +000070 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
Chris Lattner6b87b9d2009-01-05 02:07:19 +000071 SS.setEndLoc(CCLoc);
Douglas Gregor7f741122009-02-25 19:37:18 +000072 HasScopeSpecifier = true;
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +000073 }
74
Douglas Gregor7f741122009-02-25 19:37:18 +000075 while (true) {
Douglas Gregorb7bfe792009-09-02 22:59:36 +000076 if (HasScopeSpecifier) {
77 // C++ [basic.lookup.classref]p5:
78 // If the qualified-id has the form
Douglas Gregor308047d2009-09-09 00:23:06 +000079 //
Douglas Gregorb7bfe792009-09-02 22:59:36 +000080 // ::class-name-or-namespace-name::...
Douglas Gregor308047d2009-09-09 00:23:06 +000081 //
Douglas Gregorb7bfe792009-09-02 22:59:36 +000082 // the class-name-or-namespace-name is looked up in global scope as a
83 // class-name or namespace-name.
84 //
85 // To implement this, we clear out the object type as soon as we've
86 // seen a leading '::' or part of a nested-name-specifier.
87 ObjectType = 0;
Douglas Gregor2436e712009-09-17 21:32:03 +000088
89 if (Tok.is(tok::code_completion)) {
90 // Code completion for a nested-name-specifier, where the code
91 // code completion token follows the '::'.
92 Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
93 ConsumeToken();
94 }
Douglas Gregorb7bfe792009-09-02 22:59:36 +000095 }
Mike Stump11289f42009-09-09 15:08:12 +000096
Douglas Gregor7f741122009-02-25 19:37:18 +000097 // nested-name-specifier:
Chris Lattner0eed3a62009-06-26 03:47:46 +000098 // nested-name-specifier 'template'[opt] simple-template-id '::'
99
100 // Parse the optional 'template' keyword, then make sure we have
101 // 'identifier <' after it.
102 if (Tok.is(tok::kw_template)) {
Douglas Gregorb7bfe792009-09-02 22:59:36 +0000103 // If we don't have a scope specifier or an object type, this isn't a
Eli Friedman2624be42009-08-29 04:08:08 +0000104 // nested-name-specifier, since they aren't allowed to start with
105 // 'template'.
Douglas Gregorb7bfe792009-09-02 22:59:36 +0000106 if (!HasScopeSpecifier && !ObjectType)
Eli Friedman2624be42009-08-29 04:08:08 +0000107 break;
108
Chris Lattner0eed3a62009-06-26 03:47:46 +0000109 SourceLocation TemplateKWLoc = ConsumeToken();
Mike Stump11289f42009-09-09 15:08:12 +0000110
Chris Lattner0eed3a62009-06-26 03:47:46 +0000111 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +0000112 Diag(Tok.getLocation(),
Chris Lattner0eed3a62009-06-26 03:47:46 +0000113 diag::err_id_after_template_in_nested_name_spec)
114 << SourceRange(TemplateKWLoc);
115 break;
116 }
Mike Stump11289f42009-09-09 15:08:12 +0000117
Chris Lattner0eed3a62009-06-26 03:47:46 +0000118 if (NextToken().isNot(tok::less)) {
119 Diag(NextToken().getLocation(),
120 diag::err_less_after_template_name_in_nested_name_spec)
121 << Tok.getIdentifierInfo()->getName()
122 << SourceRange(TemplateKWLoc, Tok.getLocation());
123 break;
124 }
Mike Stump11289f42009-09-09 15:08:12 +0000125
126 TemplateTy Template
Chris Lattner0eed3a62009-06-26 03:47:46 +0000127 = Actions.ActOnDependentTemplateName(TemplateKWLoc,
128 *Tok.getIdentifierInfo(),
Douglas Gregorb7bfe792009-09-02 22:59:36 +0000129 Tok.getLocation(), SS,
130 ObjectType);
Eli Friedman2624be42009-08-29 04:08:08 +0000131 if (!Template)
132 break;
Chris Lattner5558e9f2009-06-26 04:27:47 +0000133 if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
134 &SS, TemplateKWLoc, false))
135 break;
Mike Stump11289f42009-09-09 15:08:12 +0000136
Chris Lattner0eed3a62009-06-26 03:47:46 +0000137 continue;
138 }
Mike Stump11289f42009-09-09 15:08:12 +0000139
Douglas Gregor7f741122009-02-25 19:37:18 +0000140 if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
Mike Stump11289f42009-09-09 15:08:12 +0000141 // We have
Douglas Gregor7f741122009-02-25 19:37:18 +0000142 //
143 // simple-template-id '::'
144 //
145 // So we need to check whether the simple-template-id is of the
Douglas Gregorb67535d2009-03-31 00:43:58 +0000146 // right kind (it should name a type or be dependent), and then
147 // convert it into a type within the nested-name-specifier.
Mike Stump11289f42009-09-09 15:08:12 +0000148 TemplateIdAnnotation *TemplateId
Douglas Gregor7f741122009-02-25 19:37:18 +0000149 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
150
Mike Stump11289f42009-09-09 15:08:12 +0000151 if (TemplateId->Kind == TNK_Type_template ||
Douglas Gregorb67535d2009-03-31 00:43:58 +0000152 TemplateId->Kind == TNK_Dependent_template_name) {
Douglas Gregorfe3d7d02009-04-01 21:51:26 +0000153 AnnotateTemplateIdTokenAsType(&SS);
Douglas Gregor7f741122009-02-25 19:37:18 +0000154
Mike Stump11289f42009-09-09 15:08:12 +0000155 assert(Tok.is(tok::annot_typename) &&
Douglas Gregor7f741122009-02-25 19:37:18 +0000156 "AnnotateTemplateIdTokenAsType isn't working");
Douglas Gregor7f741122009-02-25 19:37:18 +0000157 Token TypeToken = Tok;
158 ConsumeToken();
159 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
160 SourceLocation CCLoc = ConsumeToken();
Mike Stump11289f42009-09-09 15:08:12 +0000161
Douglas Gregor7f741122009-02-25 19:37:18 +0000162 if (!HasScopeSpecifier) {
163 SS.setBeginLoc(TypeToken.getLocation());
164 HasScopeSpecifier = true;
165 }
Mike Stump11289f42009-09-09 15:08:12 +0000166
Douglas Gregorfe3d7d02009-04-01 21:51:26 +0000167 if (TypeToken.getAnnotationValue())
168 SS.setScopeRep(
Mike Stump11289f42009-09-09 15:08:12 +0000169 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
Douglas Gregorfe3d7d02009-04-01 21:51:26 +0000170 TypeToken.getAnnotationValue(),
171 TypeToken.getAnnotationRange(),
172 CCLoc));
173 else
174 SS.setScopeRep(0);
Douglas Gregor7f741122009-02-25 19:37:18 +0000175 SS.setEndLoc(CCLoc);
176 continue;
Chris Lattner704edfb2009-06-26 03:45:46 +0000177 }
Mike Stump11289f42009-09-09 15:08:12 +0000178
Chris Lattner704edfb2009-06-26 03:45:46 +0000179 assert(false && "FIXME: Only type template names supported here");
Douglas Gregor7f741122009-02-25 19:37:18 +0000180 }
181
Chris Lattnere2355f72009-06-26 03:52:38 +0000182
183 // The rest of the nested-name-specifier possibilities start with
184 // tok::identifier.
185 if (Tok.isNot(tok::identifier))
186 break;
187
188 IdentifierInfo &II = *Tok.getIdentifierInfo();
189
190 // nested-name-specifier:
191 // type-name '::'
192 // namespace-name '::'
193 // nested-name-specifier identifier '::'
194 Token Next = NextToken();
195 if (Next.is(tok::coloncolon)) {
196 // We have an identifier followed by a '::'. Lookup this name
197 // as the name in a nested-name-specifier.
198 SourceLocation IdLoc = ConsumeToken();
199 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
200 SourceLocation CCLoc = ConsumeToken();
Mike Stump11289f42009-09-09 15:08:12 +0000201
Chris Lattnere2355f72009-06-26 03:52:38 +0000202 if (!HasScopeSpecifier) {
203 SS.setBeginLoc(IdLoc);
204 HasScopeSpecifier = true;
205 }
Mike Stump11289f42009-09-09 15:08:12 +0000206
Chris Lattnere2355f72009-06-26 03:52:38 +0000207 if (SS.isInvalid())
208 continue;
Mike Stump11289f42009-09-09 15:08:12 +0000209
Chris Lattnere2355f72009-06-26 03:52:38 +0000210 SS.setScopeRep(
Douglas Gregore861bac2009-08-25 22:51:20 +0000211 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
Douglas Gregorb7bfe792009-09-02 22:59:36 +0000212 ObjectType, EnteringContext));
Chris Lattnere2355f72009-06-26 03:52:38 +0000213 SS.setEndLoc(CCLoc);
214 continue;
215 }
Mike Stump11289f42009-09-09 15:08:12 +0000216
Chris Lattnere2355f72009-06-26 03:52:38 +0000217 // nested-name-specifier:
218 // type-name '<'
219 if (Next.is(tok::less)) {
220 TemplateTy Template;
Douglas Gregorb7bfe792009-09-02 22:59:36 +0000221 if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II,
222 Tok.getLocation(),
223 &SS,
224 ObjectType,
Douglas Gregore861bac2009-08-25 22:51:20 +0000225 EnteringContext,
226 Template)) {
Chris Lattnere2355f72009-06-26 03:52:38 +0000227 // We have found a template name, so annotate this this token
228 // with a template-id annotation. We do not permit the
229 // template-id to be translated into a type annotation,
230 // because some clients (e.g., the parsing of class template
231 // specializations) still want to see the original template-id
232 // token.
Chris Lattner5558e9f2009-06-26 04:27:47 +0000233 if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(),
234 false))
235 break;
Chris Lattnere2355f72009-06-26 03:52:38 +0000236 continue;
237 }
238 }
239
Douglas Gregor7f741122009-02-25 19:37:18 +0000240 // We don't have any tokens that form the beginning of a
241 // nested-name-specifier, so we're done.
242 break;
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000243 }
Mike Stump11289f42009-09-09 15:08:12 +0000244
Douglas Gregor7f741122009-02-25 19:37:18 +0000245 return HasScopeSpecifier;
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000246}
247
248/// ParseCXXIdExpression - Handle id-expression.
249///
250/// id-expression:
251/// unqualified-id
252/// qualified-id
253///
254/// unqualified-id:
255/// identifier
256/// operator-function-id
257/// conversion-function-id [TODO]
258/// '~' class-name [TODO]
Douglas Gregora727cb92009-06-30 22:34:41 +0000259/// template-id
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000260///
261/// qualified-id:
262/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
263/// '::' identifier
264/// '::' operator-function-id
Douglas Gregora727cb92009-06-30 22:34:41 +0000265/// '::' template-id
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000266///
267/// nested-name-specifier:
268/// type-name '::'
269/// namespace-name '::'
270/// nested-name-specifier identifier '::'
271/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
272///
273/// NOTE: The standard specifies that, for qualified-id, the parser does not
274/// expect:
275///
276/// '::' conversion-function-id
277/// '::' '~' class-name
278///
279/// This may cause a slight inconsistency on diagnostics:
280///
281/// class C {};
282/// namespace A {}
283/// void f() {
284/// :: A :: ~ C(); // Some Sema error about using destructor with a
285/// // namespace.
286/// :: ~ C(); // Some Parser error like 'unexpected ~'.
287/// }
288///
289/// We simplify the parser a bit and make it work like:
290///
291/// qualified-id:
292/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
293/// '::' unqualified-id
294///
295/// That way Sema can handle and report similar errors for namespaces and the
296/// global scope.
297///
Sebastian Redl3d3f75a2009-02-03 20:19:35 +0000298/// The isAddressOfOperand parameter indicates that this id-expression is a
299/// direct operand of the address-of operator. This is, besides member contexts,
300/// the only place where a qualified-id naming a non-static class member may
301/// appear.
302///
303Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000304 // qualified-id:
305 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
306 // '::' unqualified-id
307 //
308 CXXScopeSpec SS;
Douglas Gregorb7bfe792009-09-02 22:59:36 +0000309 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000310
311 // unqualified-id:
312 // identifier
313 // operator-function-id
Douglas Gregorae2fbad2008-11-17 20:34:05 +0000314 // conversion-function-id
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000315 // '~' class-name [TODO]
Douglas Gregora727cb92009-06-30 22:34:41 +0000316 // template-id
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000317 //
318 switch (Tok.getKind()) {
319 default:
Sebastian Redld65cea82008-12-11 22:51:44 +0000320 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000321
322 case tok::identifier: {
323 // Consume the identifier so that we can see if it is followed by a '('.
324 IdentifierInfo &II = *Tok.getIdentifierInfo();
325 SourceLocation L = ConsumeToken();
Sebastian Redl3d3f75a2009-02-03 20:19:35 +0000326 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
327 &SS, isAddressOfOperand);
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000328 }
329
330 case tok::kw_operator: {
331 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattnerb5134c02009-01-05 01:24:05 +0000332 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redlffbcf962009-01-18 18:53:16 +0000333 return Actions.ActOnCXXOperatorFunctionIdExpr(
Sebastian Redl3d3f75a2009-02-03 20:19:35 +0000334 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
335 isAddressOfOperand);
Chris Lattnerb5134c02009-01-05 01:24:05 +0000336 if (TypeTy *Type = ParseConversionFunctionId())
Sebastian Redlffbcf962009-01-18 18:53:16 +0000337 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
Sebastian Redl3d3f75a2009-02-03 20:19:35 +0000338 Tok.is(tok::l_paren), SS,
339 isAddressOfOperand);
Sebastian Redld65cea82008-12-11 22:51:44 +0000340
Douglas Gregorae2fbad2008-11-17 20:34:05 +0000341 // We already complained about a bad conversion-function-id,
342 // above.
Sebastian Redld65cea82008-12-11 22:51:44 +0000343 return ExprError();
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000344 }
345
Douglas Gregora727cb92009-06-30 22:34:41 +0000346 case tok::annot_template_id: {
Mike Stump11289f42009-09-09 15:08:12 +0000347 TemplateIdAnnotation *TemplateId
Douglas Gregora727cb92009-06-30 22:34:41 +0000348 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
349 assert((TemplateId->Kind == TNK_Function_template ||
350 TemplateId->Kind == TNK_Dependent_template_name) &&
351 "A template type name is not an ID expression");
352
Mike Stump11289f42009-09-09 15:08:12 +0000353 ASTTemplateArgsPtr TemplateArgsPtr(Actions,
Douglas Gregora727cb92009-06-30 22:34:41 +0000354 TemplateId->getTemplateArgs(),
355 TemplateId->getTemplateArgIsType(),
356 TemplateId->NumArgs);
Mike Stump11289f42009-09-09 15:08:12 +0000357
Douglas Gregora727cb92009-06-30 22:34:41 +0000358 OwningExprResult Result
Douglas Gregord019ff62009-10-22 17:20:55 +0000359 = Actions.ActOnTemplateIdExpr(SS,
360 TemplateTy::make(TemplateId->Template),
Douglas Gregora727cb92009-06-30 22:34:41 +0000361 TemplateId->TemplateNameLoc,
362 TemplateId->LAngleLoc,
363 TemplateArgsPtr,
364 TemplateId->getTemplateArgLocations(),
365 TemplateId->RAngleLoc);
366 ConsumeToken(); // Consume the template-id token
367 return move(Result);
368 }
369
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000370 } // switch.
371
372 assert(0 && "The switch was supposed to take care everything.");
373}
374
Chris Lattner29375652006-12-04 18:06:35 +0000375/// ParseCXXCasts - This handles the various ways to cast expressions to another
376/// type.
377///
378/// postfix-expression: [C++ 5.2p1]
379/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
380/// 'static_cast' '<' type-name '>' '(' expression ')'
381/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
382/// 'const_cast' '<' type-name '>' '(' expression ')'
383///
Sebastian Redld65cea82008-12-11 22:51:44 +0000384Parser::OwningExprResult Parser::ParseCXXCasts() {
Chris Lattner29375652006-12-04 18:06:35 +0000385 tok::TokenKind Kind = Tok.getKind();
386 const char *CastName = 0; // For error messages
387
388 switch (Kind) {
389 default: assert(0 && "Unknown C++ cast!"); abort();
390 case tok::kw_const_cast: CastName = "const_cast"; break;
391 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
392 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
393 case tok::kw_static_cast: CastName = "static_cast"; break;
394 }
395
396 SourceLocation OpLoc = ConsumeToken();
397 SourceLocation LAngleBracketLoc = Tok.getLocation();
398
399 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redld65cea82008-12-11 22:51:44 +0000400 return ExprError();
Chris Lattner29375652006-12-04 18:06:35 +0000401
Douglas Gregor220cac52009-02-18 17:45:20 +0000402 TypeResult CastTy = ParseTypeName();
Chris Lattner29375652006-12-04 18:06:35 +0000403 SourceLocation RAngleBracketLoc = Tok.getLocation();
404
Chris Lattner6d29c102008-11-18 07:48:38 +0000405 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redld65cea82008-12-11 22:51:44 +0000406 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Chris Lattner29375652006-12-04 18:06:35 +0000407
408 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
409
Argyrios Kyrtzidis387a3342009-05-22 10:23:16 +0000410 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
411 return ExprError();
Chris Lattner29375652006-12-04 18:06:35 +0000412
Argyrios Kyrtzidis387a3342009-05-22 10:23:16 +0000413 OwningExprResult Result = ParseExpression();
Mike Stump11289f42009-09-09 15:08:12 +0000414
Argyrios Kyrtzidis387a3342009-05-22 10:23:16 +0000415 // Match the ')'.
416 if (Result.isInvalid())
417 SkipUntil(tok::r_paren);
Mike Stump11289f42009-09-09 15:08:12 +0000418
Argyrios Kyrtzidis387a3342009-05-22 10:23:16 +0000419 if (Tok.is(tok::r_paren))
420 RParenLoc = ConsumeParen();
421 else
422 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Chris Lattner29375652006-12-04 18:06:35 +0000423
Douglas Gregor220cac52009-02-18 17:45:20 +0000424 if (!Result.isInvalid() && !CastTy.isInvalid())
Douglas Gregore200adc2008-10-27 19:41:14 +0000425 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000426 LAngleBracketLoc, CastTy.get(),
Douglas Gregor220cac52009-02-18 17:45:20 +0000427 RAngleBracketLoc,
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000428 LParenLoc, move(Result), RParenLoc);
Chris Lattner29375652006-12-04 18:06:35 +0000429
Sebastian Redld65cea82008-12-11 22:51:44 +0000430 return move(Result);
Chris Lattner29375652006-12-04 18:06:35 +0000431}
Bill Wendling4073ed52007-02-13 01:51:42 +0000432
Sebastian Redlc4704762008-11-11 11:37:55 +0000433/// ParseCXXTypeid - This handles the C++ typeid expression.
434///
435/// postfix-expression: [C++ 5.2p1]
436/// 'typeid' '(' expression ')'
437/// 'typeid' '(' type-id ')'
438///
Sebastian Redld65cea82008-12-11 22:51:44 +0000439Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc4704762008-11-11 11:37:55 +0000440 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
441
442 SourceLocation OpLoc = ConsumeToken();
443 SourceLocation LParenLoc = Tok.getLocation();
444 SourceLocation RParenLoc;
445
446 // typeid expressions are always parenthesized.
447 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
448 "typeid"))
Sebastian Redld65cea82008-12-11 22:51:44 +0000449 return ExprError();
Sebastian Redlc4704762008-11-11 11:37:55 +0000450
Sebastian Redlc13f2682008-12-09 20:22:58 +0000451 OwningExprResult Result(Actions);
Sebastian Redlc4704762008-11-11 11:37:55 +0000452
453 if (isTypeIdInParens()) {
Douglas Gregor220cac52009-02-18 17:45:20 +0000454 TypeResult Ty = ParseTypeName();
Sebastian Redlc4704762008-11-11 11:37:55 +0000455
456 // Match the ')'.
457 MatchRHSPunctuation(tok::r_paren, LParenLoc);
458
Douglas Gregor220cac52009-02-18 17:45:20 +0000459 if (Ty.isInvalid())
Sebastian Redld65cea82008-12-11 22:51:44 +0000460 return ExprError();
Sebastian Redlc4704762008-11-11 11:37:55 +0000461
462 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Douglas Gregor220cac52009-02-18 17:45:20 +0000463 Ty.get(), RParenLoc);
Sebastian Redlc4704762008-11-11 11:37:55 +0000464 } else {
Douglas Gregorc9c02ed2009-06-19 23:52:42 +0000465 // C++0x [expr.typeid]p3:
Mike Stump11289f42009-09-09 15:08:12 +0000466 // When typeid is applied to an expression other than an lvalue of a
467 // polymorphic class type [...] The expression is an unevaluated
Douglas Gregorc9c02ed2009-06-19 23:52:42 +0000468 // operand (Clause 5).
469 //
Mike Stump11289f42009-09-09 15:08:12 +0000470 // Note that we can't tell whether the expression is an lvalue of a
Douglas Gregorc9c02ed2009-06-19 23:52:42 +0000471 // polymorphic class type until after we've parsed the expression, so
Douglas Gregor0b6a6242009-06-22 20:57:11 +0000472 // we the expression is potentially potentially evaluated.
473 EnterExpressionEvaluationContext Unevaluated(Actions,
474 Action::PotentiallyPotentiallyEvaluated);
Sebastian Redlc4704762008-11-11 11:37:55 +0000475 Result = ParseExpression();
476
477 // Match the ')'.
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000478 if (Result.isInvalid())
Sebastian Redlc4704762008-11-11 11:37:55 +0000479 SkipUntil(tok::r_paren);
480 else {
481 MatchRHSPunctuation(tok::r_paren, LParenLoc);
482
483 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redld9f7b1c2008-12-10 00:02:53 +0000484 Result.release(), RParenLoc);
Sebastian Redlc4704762008-11-11 11:37:55 +0000485 }
486 }
487
Sebastian Redld65cea82008-12-11 22:51:44 +0000488 return move(Result);
Sebastian Redlc4704762008-11-11 11:37:55 +0000489}
490
Bill Wendling4073ed52007-02-13 01:51:42 +0000491/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
492///
493/// boolean-literal: [C++ 2.13.5]
494/// 'true'
495/// 'false'
Sebastian Redld65cea82008-12-11 22:51:44 +0000496Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Bill Wendling4073ed52007-02-13 01:51:42 +0000497 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000498 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
Bill Wendling4073ed52007-02-13 01:51:42 +0000499}
Chris Lattnerb7e656b2008-02-26 00:51:44 +0000500
501/// ParseThrowExpression - This handles the C++ throw expression.
502///
503/// throw-expression: [C++ 15]
504/// 'throw' assignment-expression[opt]
Sebastian Redld65cea82008-12-11 22:51:44 +0000505Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattnerb7e656b2008-02-26 00:51:44 +0000506 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattnerb7e656b2008-02-26 00:51:44 +0000507 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redld65cea82008-12-11 22:51:44 +0000508
Chris Lattner65dd8432008-04-06 06:02:23 +0000509 // If the current token isn't the start of an assignment-expression,
510 // then the expression is not present. This handles things like:
511 // "C ? throw : (void)42", which is crazy but legal.
512 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
513 case tok::semi:
514 case tok::r_paren:
515 case tok::r_square:
516 case tok::r_brace:
517 case tok::colon:
518 case tok::comma:
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000519 return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
Chris Lattnerb7e656b2008-02-26 00:51:44 +0000520
Chris Lattner65dd8432008-04-06 06:02:23 +0000521 default:
Sebastian Redl59b5e512008-12-11 21:36:32 +0000522 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redld65cea82008-12-11 22:51:44 +0000523 if (Expr.isInvalid()) return move(Expr);
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000524 return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
Chris Lattner65dd8432008-04-06 06:02:23 +0000525 }
Chris Lattnerb7e656b2008-02-26 00:51:44 +0000526}
Argyrios Kyrtzidis7bbb20e2008-06-24 22:12:16 +0000527
528/// ParseCXXThis - This handles the C++ 'this' pointer.
529///
530/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
531/// a non-lvalue expression whose value is the address of the object for which
532/// the function is called.
Sebastian Redld65cea82008-12-11 22:51:44 +0000533Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis7bbb20e2008-06-24 22:12:16 +0000534 assert(Tok.is(tok::kw_this) && "Not 'this'!");
535 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000536 return Actions.ActOnCXXThis(ThisLoc);
Argyrios Kyrtzidis7bbb20e2008-06-24 22:12:16 +0000537}
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000538
539/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
540/// Can be interpreted either as function-style casting ("int(x)")
541/// or class type construction ("ClassType(x,y,z)")
542/// or creation of a value-initialized type ("int()").
543///
544/// postfix-expression: [C++ 5.2p1]
545/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
546/// typename-specifier '(' expression-list[opt] ')' [TODO]
547///
Sebastian Redld65cea82008-12-11 22:51:44 +0000548Parser::OwningExprResult
549Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000550 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Douglas Gregorf8298252009-01-26 22:44:13 +0000551 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000552
553 assert(Tok.is(tok::l_paren) && "Expected '('!");
554 SourceLocation LParenLoc = ConsumeParen();
555
Sebastian Redl511ed552008-11-25 22:21:31 +0000556 ExprVector Exprs(Actions);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000557 CommaLocsTy CommaLocs;
558
559 if (Tok.isNot(tok::r_paren)) {
560 if (ParseExpressionList(Exprs, CommaLocs)) {
561 SkipUntil(tok::r_paren);
Sebastian Redld65cea82008-12-11 22:51:44 +0000562 return ExprError();
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000563 }
564 }
565
566 // Match the ')'.
567 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
568
Sebastian Redl955a0672009-07-29 13:50:23 +0000569 // TypeRep could be null, if it references an invalid typedef.
570 if (!TypeRep)
571 return ExprError();
572
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000573 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
574 "Unexpected number of commas!");
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000575 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
576 LParenLoc, move_arg(Exprs),
Jay Foad7d0479f2009-05-21 09:52:38 +0000577 CommaLocs.data(), RParenLoc);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000578}
579
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000580/// ParseCXXCondition - if/switch/while/for condition expression.
581///
582/// condition:
583/// expression
584/// type-specifier-seq declarator '=' assignment-expression
585/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
586/// '=' assignment-expression
587///
Sebastian Redl59b5e512008-12-11 21:36:32 +0000588Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidis71f3e192008-10-05 15:03:47 +0000589 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000590 return ParseExpression(); // expression
591
592 SourceLocation StartLoc = Tok.getLocation();
593
594 // type-specifier-seq
595 DeclSpec DS;
596 ParseSpecifierQualifierList(DS);
597
598 // declarator
599 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
600 ParseDeclarator(DeclaratorInfo);
601
602 // simple-asm-expr[opt]
603 if (Tok.is(tok::kw_asm)) {
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000604 SourceLocation Loc;
605 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000606 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000607 SkipUntil(tok::semi);
Sebastian Redl59b5e512008-12-11 21:36:32 +0000608 return ExprError();
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000609 }
Sebastian Redld9f7b1c2008-12-10 00:02:53 +0000610 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000611 DeclaratorInfo.SetRangeEnd(Loc);
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000612 }
613
614 // If attributes are present, parse them.
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000615 if (Tok.is(tok::kw___attribute)) {
616 SourceLocation Loc;
617 AttributeList *AttrList = ParseAttributes(&Loc);
618 DeclaratorInfo.AddAttributes(AttrList, Loc);
619 }
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000620
621 // '=' assignment-expression
622 if (Tok.isNot(tok::equal))
Sebastian Redl59b5e512008-12-11 21:36:32 +0000623 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000624 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl59b5e512008-12-11 21:36:32 +0000625 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000626 if (AssignExpr.isInvalid())
Sebastian Redl59b5e512008-12-11 21:36:32 +0000627 return ExprError();
628
Sebastian Redl6d4256c2009-03-15 17:47:39 +0000629 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
630 DeclaratorInfo,EqualLoc,
631 move(AssignExpr));
Argyrios Kyrtzidis2b4072f2008-09-09 20:38:47 +0000632}
633
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000634/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
635/// This should only be called when the current token is known to be part of
636/// simple-type-specifier.
637///
638/// simple-type-specifier:
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000639/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000640/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
641/// char
642/// wchar_t
643/// bool
644/// short
645/// int
646/// long
647/// signed
648/// unsigned
649/// float
650/// double
651/// void
652/// [GNU] typeof-specifier
653/// [C++0x] auto [TODO]
654///
655/// type-name:
656/// class-name
657/// enum-name
658/// typedef-name
659///
660void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
661 DS.SetRangeStart(Tok.getLocation());
662 const char *PrevSpec;
John McCall49bfce42009-08-03 20:12:06 +0000663 unsigned DiagID;
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000664 SourceLocation Loc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000665
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000666 switch (Tok.getKind()) {
Chris Lattner45ddec32009-01-05 00:13:00 +0000667 case tok::identifier: // foo::bar
668 case tok::coloncolon: // ::foo::bar
669 assert(0 && "Annotation token should already be formed!");
Mike Stump11289f42009-09-09 15:08:12 +0000670 default:
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000671 assert(0 && "Not a simple-type-specifier token!");
672 abort();
Chris Lattner45ddec32009-01-05 00:13:00 +0000673
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000674 // type-name
Chris Lattnera8a3f732009-01-06 05:06:21 +0000675 case tok::annot_typename: {
John McCall49bfce42009-08-03 20:12:06 +0000676 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000677 Tok.getAnnotationValue());
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000678 break;
679 }
Mike Stump11289f42009-09-09 15:08:12 +0000680
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000681 // builtin types
682 case tok::kw_short:
John McCall49bfce42009-08-03 20:12:06 +0000683 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000684 break;
685 case tok::kw_long:
John McCall49bfce42009-08-03 20:12:06 +0000686 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000687 break;
688 case tok::kw_signed:
John McCall49bfce42009-08-03 20:12:06 +0000689 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000690 break;
691 case tok::kw_unsigned:
John McCall49bfce42009-08-03 20:12:06 +0000692 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000693 break;
694 case tok::kw_void:
John McCall49bfce42009-08-03 20:12:06 +0000695 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000696 break;
697 case tok::kw_char:
John McCall49bfce42009-08-03 20:12:06 +0000698 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000699 break;
700 case tok::kw_int:
John McCall49bfce42009-08-03 20:12:06 +0000701 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000702 break;
703 case tok::kw_float:
John McCall49bfce42009-08-03 20:12:06 +0000704 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000705 break;
706 case tok::kw_double:
John McCall49bfce42009-08-03 20:12:06 +0000707 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000708 break;
709 case tok::kw_wchar_t:
John McCall49bfce42009-08-03 20:12:06 +0000710 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000711 break;
Alisdair Mereditha9ad47d2009-07-14 06:30:34 +0000712 case tok::kw_char16_t:
John McCall49bfce42009-08-03 20:12:06 +0000713 DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
Alisdair Mereditha9ad47d2009-07-14 06:30:34 +0000714 break;
715 case tok::kw_char32_t:
John McCall49bfce42009-08-03 20:12:06 +0000716 DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
Alisdair Mereditha9ad47d2009-07-14 06:30:34 +0000717 break;
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000718 case tok::kw_bool:
John McCall49bfce42009-08-03 20:12:06 +0000719 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000720 break;
Mike Stump11289f42009-09-09 15:08:12 +0000721
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000722 // GNU typeof support.
723 case tok::kw_typeof:
724 ParseTypeofSpecifier(DS);
Douglas Gregore3e01a22009-04-01 22:41:11 +0000725 DS.Finish(Diags, PP);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000726 return;
727 }
Chris Lattnera8a3f732009-01-06 05:06:21 +0000728 if (Tok.is(tok::annot_typename))
Argyrios Kyrtzidis32a03792008-11-08 16:45:02 +0000729 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
730 else
731 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000732 ConsumeToken();
Douglas Gregore3e01a22009-04-01 22:41:11 +0000733 DS.Finish(Diags, PP);
Argyrios Kyrtzidis857fcc22008-08-22 15:38:55 +0000734}
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000735
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000736/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
737/// [dcl.name]), which is a non-empty sequence of type-specifiers,
738/// e.g., "const short int". Note that the DeclSpec is *not* finished
739/// by parsing the type-specifier-seq, because these sequences are
740/// typically followed by some form of declarator. Returns true and
741/// emits diagnostics if this is not a type-specifier-seq, false
742/// otherwise.
743///
744/// type-specifier-seq: [C++ 8.1]
745/// type-specifier type-specifier-seq[opt]
746///
747bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
748 DS.SetRangeStart(Tok.getLocation());
749 const char *PrevSpec = 0;
John McCall49bfce42009-08-03 20:12:06 +0000750 unsigned DiagID;
751 bool isInvalid = 0;
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000752
753 // Parse one or more of the type specifiers.
John McCall49bfce42009-08-03 20:12:06 +0000754 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) {
Chris Lattner6d29c102008-11-18 07:48:38 +0000755 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000756 return true;
757 }
Mike Stump11289f42009-09-09 15:08:12 +0000758
John McCall49bfce42009-08-03 20:12:06 +0000759 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ;
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000760
761 return false;
762}
763
Douglas Gregord69246b2008-11-17 16:14:12 +0000764/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000765/// operator name (C++ [over.oper]). If successful, returns the
766/// predefined identifier that corresponds to that overloaded
767/// operator. Otherwise, returns NULL and does not consume any tokens.
768///
769/// operator-function-id: [C++ 13.5]
770/// 'operator' operator
771///
772/// operator: one of
773/// new delete new[] delete[]
774/// + - * / % ^ & | ~
775/// ! = < > += -= *= /= %=
776/// ^= &= |= << >> >>= <<= == !=
777/// <= >= && || ++ -- , ->* ->
778/// () []
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000779OverloadedOperatorKind
780Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
Argyrios Kyrtzidis56fa31b2008-11-07 15:54:02 +0000781 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000782 SourceLocation Loc;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000783
784 OverloadedOperatorKind Op = OO_None;
785 switch (NextToken().getKind()) {
786 case tok::kw_new:
787 ConsumeToken(); // 'operator'
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000788 Loc = ConsumeToken(); // 'new'
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000789 if (Tok.is(tok::l_square)) {
790 ConsumeBracket(); // '['
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000791 Loc = Tok.getLocation();
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000792 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
793 Op = OO_Array_New;
794 } else {
795 Op = OO_New;
796 }
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000797 if (EndLoc)
798 *EndLoc = Loc;
Douglas Gregor163c5852008-11-18 14:39:36 +0000799 return Op;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000800
801 case tok::kw_delete:
802 ConsumeToken(); // 'operator'
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000803 Loc = ConsumeToken(); // 'delete'
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000804 if (Tok.is(tok::l_square)) {
805 ConsumeBracket(); // '['
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000806 Loc = Tok.getLocation();
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000807 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
808 Op = OO_Array_Delete;
809 } else {
810 Op = OO_Delete;
811 }
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000812 if (EndLoc)
813 *EndLoc = Loc;
Douglas Gregor163c5852008-11-18 14:39:36 +0000814 return Op;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000815
Douglas Gregor6cf08062008-11-10 13:38:07 +0000816#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000817 case tok::Token: Op = OO_##Name; break;
Douglas Gregor6cf08062008-11-10 13:38:07 +0000818#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000819#include "clang/Basic/OperatorKinds.def"
820
821 case tok::l_paren:
822 ConsumeToken(); // 'operator'
823 ConsumeParen(); // '('
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000824 Loc = Tok.getLocation();
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000825 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000826 if (EndLoc)
827 *EndLoc = Loc;
Douglas Gregor163c5852008-11-18 14:39:36 +0000828 return OO_Call;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000829
830 case tok::l_square:
831 ConsumeToken(); // 'operator'
832 ConsumeBracket(); // '['
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000833 Loc = Tok.getLocation();
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000834 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000835 if (EndLoc)
836 *EndLoc = Loc;
Douglas Gregor163c5852008-11-18 14:39:36 +0000837 return OO_Subscript;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000838
Douglas Gregorc811ede2009-09-18 20:05:18 +0000839 case tok::code_completion: {
840 // Code completion for the operator name.
841 Actions.CodeCompleteOperatorName(CurScope);
842
843 // Consume the 'operator' token, then replace the code-completion token
844 // with an 'operator' token and try again.
845 SourceLocation OperatorLoc = ConsumeToken();
846 Tok.setLocation(OperatorLoc);
847 Tok.setKind(tok::kw_operator);
848 return TryParseOperatorFunctionId(EndLoc);
849 }
850
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000851 default:
Douglas Gregor163c5852008-11-18 14:39:36 +0000852 return OO_None;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000853 }
854
Douglas Gregord69246b2008-11-17 16:14:12 +0000855 ConsumeToken(); // 'operator'
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000856 Loc = ConsumeAnyToken(); // the operator itself
857 if (EndLoc)
858 *EndLoc = Loc;
Douglas Gregor163c5852008-11-18 14:39:36 +0000859 return Op;
Douglas Gregor11d0c4c2008-11-06 22:13:31 +0000860}
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000861
862/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
863/// which expresses the name of a user-defined conversion operator
864/// (C++ [class.conv.fct]p1). Returns the type that this operator is
865/// specifying a conversion for, or NULL if there was an error.
866///
867/// conversion-function-id: [C++ 12.3.2]
868/// operator conversion-type-id
869///
870/// conversion-type-id:
871/// type-specifier-seq conversion-declarator[opt]
872///
873/// conversion-declarator:
874/// ptr-operator conversion-declarator[opt]
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000875Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000876 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
877 ConsumeToken(); // 'operator'
878
879 // Parse the type-specifier-seq.
880 DeclSpec DS;
881 if (ParseCXXTypeSpecifierSeq(DS))
882 return 0;
883
884 // Parse the conversion-declarator, which is merely a sequence of
885 // ptr-operators.
886 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redlbd150f42008-11-21 19:14:01 +0000887 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000888 if (EndLoc)
889 *EndLoc = D.getSourceRange().getEnd();
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000890
891 // Finish up the type.
892 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
Douglas Gregorf8298252009-01-26 22:44:13 +0000893 if (Result.isInvalid())
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000894 return 0;
895 else
Douglas Gregorf8298252009-01-26 22:44:13 +0000896 return Result.get();
Douglas Gregordbc5daf2008-11-07 20:08:42 +0000897}
Sebastian Redlbd150f42008-11-21 19:14:01 +0000898
899/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
900/// memory in a typesafe manner and call constructors.
Mike Stump11289f42009-09-09 15:08:12 +0000901///
Chris Lattner109faf22009-01-04 21:25:24 +0000902/// This method is called to parse the new expression after the optional :: has
903/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
904/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redlbd150f42008-11-21 19:14:01 +0000905///
906/// new-expression:
907/// '::'[opt] 'new' new-placement[opt] new-type-id
908/// new-initializer[opt]
909/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
910/// new-initializer[opt]
911///
912/// new-placement:
913/// '(' expression-list ')'
914///
Sebastian Redl351bb782008-12-02 14:43:59 +0000915/// new-type-id:
916/// type-specifier-seq new-declarator[opt]
917///
918/// new-declarator:
919/// ptr-operator new-declarator[opt]
920/// direct-new-declarator
921///
Sebastian Redlbd150f42008-11-21 19:14:01 +0000922/// new-initializer:
923/// '(' expression-list[opt] ')'
924/// [C++0x] braced-init-list [TODO]
925///
Chris Lattner109faf22009-01-04 21:25:24 +0000926Parser::OwningExprResult
927Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
928 assert(Tok.is(tok::kw_new) && "expected 'new' token");
929 ConsumeToken(); // Consume 'new'
Sebastian Redlbd150f42008-11-21 19:14:01 +0000930
931 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
932 // second form of new-expression. It can't be a new-type-id.
933
Sebastian Redl511ed552008-11-25 22:21:31 +0000934 ExprVector PlacementArgs(Actions);
Sebastian Redlbd150f42008-11-21 19:14:01 +0000935 SourceLocation PlacementLParen, PlacementRParen;
936
Sebastian Redlbd150f42008-11-21 19:14:01 +0000937 bool ParenTypeId;
Sebastian Redl351bb782008-12-02 14:43:59 +0000938 DeclSpec DS;
939 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redlbd150f42008-11-21 19:14:01 +0000940 if (Tok.is(tok::l_paren)) {
941 // If it turns out to be a placement, we change the type location.
942 PlacementLParen = ConsumeParen();
Sebastian Redl351bb782008-12-02 14:43:59 +0000943 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
944 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redld65cea82008-12-11 22:51:44 +0000945 return ExprError();
Sebastian Redl351bb782008-12-02 14:43:59 +0000946 }
Sebastian Redlbd150f42008-11-21 19:14:01 +0000947
948 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redl351bb782008-12-02 14:43:59 +0000949 if (PlacementRParen.isInvalid()) {
950 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redld65cea82008-12-11 22:51:44 +0000951 return ExprError();
Sebastian Redl351bb782008-12-02 14:43:59 +0000952 }
Sebastian Redlbd150f42008-11-21 19:14:01 +0000953
Sebastian Redl351bb782008-12-02 14:43:59 +0000954 if (PlacementArgs.empty()) {
Sebastian Redlbd150f42008-11-21 19:14:01 +0000955 // Reset the placement locations. There was no placement.
956 PlacementLParen = PlacementRParen = SourceLocation();
957 ParenTypeId = true;
958 } else {
959 // We still need the type.
960 if (Tok.is(tok::l_paren)) {
Sebastian Redl351bb782008-12-02 14:43:59 +0000961 SourceLocation LParen = ConsumeParen();
962 ParseSpecifierQualifierList(DS);
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000963 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redl351bb782008-12-02 14:43:59 +0000964 ParseDeclarator(DeclaratorInfo);
965 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redlbd150f42008-11-21 19:14:01 +0000966 ParenTypeId = true;
967 } else {
Sebastian Redl351bb782008-12-02 14:43:59 +0000968 if (ParseCXXTypeSpecifierSeq(DS))
969 DeclaratorInfo.setInvalidType(true);
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000970 else {
971 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redl351bb782008-12-02 14:43:59 +0000972 ParseDeclaratorInternal(DeclaratorInfo,
973 &Parser::ParseDirectNewDeclarator);
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000974 }
Sebastian Redlbd150f42008-11-21 19:14:01 +0000975 ParenTypeId = false;
976 }
Sebastian Redlbd150f42008-11-21 19:14:01 +0000977 }
978 } else {
Sebastian Redl351bb782008-12-02 14:43:59 +0000979 // A new-type-id is a simplified type-id, where essentially the
980 // direct-declarator is replaced by a direct-new-declarator.
981 if (ParseCXXTypeSpecifierSeq(DS))
982 DeclaratorInfo.setInvalidType(true);
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000983 else {
984 DeclaratorInfo.SetSourceRange(DS.getSourceRange());
Sebastian Redl351bb782008-12-02 14:43:59 +0000985 ParseDeclaratorInternal(DeclaratorInfo,
986 &Parser::ParseDirectNewDeclarator);
Sebastian Redlf6591ca2009-02-09 18:23:29 +0000987 }
Sebastian Redlbd150f42008-11-21 19:14:01 +0000988 ParenTypeId = false;
989 }
Chris Lattnerf6d1c9c2009-04-25 08:06:05 +0000990 if (DeclaratorInfo.isInvalidType()) {
Sebastian Redl351bb782008-12-02 14:43:59 +0000991 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redld65cea82008-12-11 22:51:44 +0000992 return ExprError();
Sebastian Redl351bb782008-12-02 14:43:59 +0000993 }
Sebastian Redlbd150f42008-11-21 19:14:01 +0000994
Sebastian Redl511ed552008-11-25 22:21:31 +0000995 ExprVector ConstructorArgs(Actions);
Sebastian Redlbd150f42008-11-21 19:14:01 +0000996 SourceLocation ConstructorLParen, ConstructorRParen;
997
998 if (Tok.is(tok::l_paren)) {
999 ConstructorLParen = ConsumeParen();
1000 if (Tok.isNot(tok::r_paren)) {
1001 CommaLocsTy CommaLocs;
Sebastian Redl351bb782008-12-02 14:43:59 +00001002 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
1003 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redld65cea82008-12-11 22:51:44 +00001004 return ExprError();
Sebastian Redl351bb782008-12-02 14:43:59 +00001005 }
Sebastian Redlbd150f42008-11-21 19:14:01 +00001006 }
1007 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redl351bb782008-12-02 14:43:59 +00001008 if (ConstructorRParen.isInvalid()) {
1009 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redld65cea82008-12-11 22:51:44 +00001010 return ExprError();
Sebastian Redl351bb782008-12-02 14:43:59 +00001011 }
Sebastian Redlbd150f42008-11-21 19:14:01 +00001012 }
1013
Sebastian Redl6d4256c2009-03-15 17:47:39 +00001014 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
1015 move_arg(PlacementArgs), PlacementRParen,
1016 ParenTypeId, DeclaratorInfo, ConstructorLParen,
1017 move_arg(ConstructorArgs), ConstructorRParen);
Sebastian Redlbd150f42008-11-21 19:14:01 +00001018}
1019
Sebastian Redlbd150f42008-11-21 19:14:01 +00001020/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
1021/// passed to ParseDeclaratorInternal.
1022///
1023/// direct-new-declarator:
1024/// '[' expression ']'
1025/// direct-new-declarator '[' constant-expression ']'
1026///
Chris Lattner109faf22009-01-04 21:25:24 +00001027void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redlbd150f42008-11-21 19:14:01 +00001028 // Parse the array dimensions.
1029 bool first = true;
1030 while (Tok.is(tok::l_square)) {
1031 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl59b5e512008-12-11 21:36:32 +00001032 OwningExprResult Size(first ? ParseExpression()
1033 : ParseConstantExpression());
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001034 if (Size.isInvalid()) {
Sebastian Redlbd150f42008-11-21 19:14:01 +00001035 // Recover
1036 SkipUntil(tok::r_square);
1037 return;
1038 }
1039 first = false;
1040
Sebastian Redlf6591ca2009-02-09 18:23:29 +00001041 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
Sebastian Redlbd150f42008-11-21 19:14:01 +00001042 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Douglas Gregor04318252009-07-06 15:59:29 +00001043 Size.release(), LLoc, RLoc),
Sebastian Redlf6591ca2009-02-09 18:23:29 +00001044 RLoc);
Sebastian Redlbd150f42008-11-21 19:14:01 +00001045
Sebastian Redlf6591ca2009-02-09 18:23:29 +00001046 if (RLoc.isInvalid())
Sebastian Redlbd150f42008-11-21 19:14:01 +00001047 return;
1048 }
1049}
1050
1051/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
1052/// This ambiguity appears in the syntax of the C++ new operator.
1053///
1054/// new-expression:
1055/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
1056/// new-initializer[opt]
1057///
1058/// new-placement:
1059/// '(' expression-list ')'
1060///
Sebastian Redl351bb782008-12-02 14:43:59 +00001061bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner109faf22009-01-04 21:25:24 +00001062 Declarator &D) {
Sebastian Redlbd150f42008-11-21 19:14:01 +00001063 // The '(' was already consumed.
1064 if (isTypeIdInParens()) {
Sebastian Redl351bb782008-12-02 14:43:59 +00001065 ParseSpecifierQualifierList(D.getMutableDeclSpec());
Sebastian Redlf6591ca2009-02-09 18:23:29 +00001066 D.SetSourceRange(D.getDeclSpec().getSourceRange());
Sebastian Redl351bb782008-12-02 14:43:59 +00001067 ParseDeclarator(D);
Chris Lattnerf6d1c9c2009-04-25 08:06:05 +00001068 return D.isInvalidType();
Sebastian Redlbd150f42008-11-21 19:14:01 +00001069 }
1070
1071 // It's not a type, it has to be an expression list.
1072 // Discard the comma locations - ActOnCXXNew has enough parameters.
1073 CommaLocsTy CommaLocs;
1074 return ParseExpressionList(PlacementArgs, CommaLocs);
1075}
1076
1077/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
1078/// to free memory allocated by new.
1079///
Chris Lattner109faf22009-01-04 21:25:24 +00001080/// This method is called to parse the 'delete' expression after the optional
1081/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
1082/// and "Start" is its location. Otherwise, "Start" is the location of the
1083/// 'delete' token.
1084///
Sebastian Redlbd150f42008-11-21 19:14:01 +00001085/// delete-expression:
1086/// '::'[opt] 'delete' cast-expression
1087/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner109faf22009-01-04 21:25:24 +00001088Parser::OwningExprResult
1089Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
1090 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
1091 ConsumeToken(); // Consume 'delete'
Sebastian Redlbd150f42008-11-21 19:14:01 +00001092
1093 // Array delete?
1094 bool ArrayDelete = false;
1095 if (Tok.is(tok::l_square)) {
1096 ArrayDelete = true;
1097 SourceLocation LHS = ConsumeBracket();
1098 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
1099 if (RHS.isInvalid())
Sebastian Redld65cea82008-12-11 22:51:44 +00001100 return ExprError();
Sebastian Redlbd150f42008-11-21 19:14:01 +00001101 }
1102
Sebastian Redl59b5e512008-12-11 21:36:32 +00001103 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001104 if (Operand.isInvalid())
Sebastian Redld65cea82008-12-11 22:51:44 +00001105 return move(Operand);
Sebastian Redlbd150f42008-11-21 19:14:01 +00001106
Sebastian Redl6d4256c2009-03-15 17:47:39 +00001107 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
Sebastian Redlbd150f42008-11-21 19:14:01 +00001108}
Sebastian Redlbaad4e72009-01-05 20:52:13 +00001109
Mike Stump11289f42009-09-09 15:08:12 +00001110static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
Sebastian Redlbaad4e72009-01-05 20:52:13 +00001111 switch(kind) {
1112 default: assert(false && "Not a known unary type trait.");
1113 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
1114 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
1115 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
1116 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
1117 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
1118 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
1119 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
1120 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
1121 case tok::kw___is_abstract: return UTT_IsAbstract;
1122 case tok::kw___is_class: return UTT_IsClass;
1123 case tok::kw___is_empty: return UTT_IsEmpty;
1124 case tok::kw___is_enum: return UTT_IsEnum;
1125 case tok::kw___is_pod: return UTT_IsPOD;
1126 case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
1127 case tok::kw___is_union: return UTT_IsUnion;
1128 }
1129}
1130
1131/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
1132/// pseudo-functions that allow implementation of the TR1/C++0x type traits
1133/// templates.
1134///
1135/// primary-expression:
1136/// [GNU] unary-type-trait '(' type-id ')'
1137///
Mike Stump11289f42009-09-09 15:08:12 +00001138Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
Sebastian Redlbaad4e72009-01-05 20:52:13 +00001139 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
1140 SourceLocation Loc = ConsumeToken();
1141
1142 SourceLocation LParen = Tok.getLocation();
1143 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1144 return ExprError();
1145
1146 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
1147 // there will be cryptic errors about mismatched parentheses and missing
1148 // specifiers.
Douglas Gregor220cac52009-02-18 17:45:20 +00001149 TypeResult Ty = ParseTypeName();
Sebastian Redlbaad4e72009-01-05 20:52:13 +00001150
1151 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
1152
Douglas Gregor220cac52009-02-18 17:45:20 +00001153 if (Ty.isInvalid())
1154 return ExprError();
1155
1156 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
Sebastian Redlbaad4e72009-01-05 20:52:13 +00001157}
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001158
1159/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
1160/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
1161/// based on the context past the parens.
1162Parser::OwningExprResult
1163Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
1164 TypeTy *&CastTy,
1165 SourceLocation LParenLoc,
1166 SourceLocation &RParenLoc) {
1167 assert(getLang().CPlusPlus && "Should only be called for C++!");
1168 assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
1169 assert(isTypeIdInParens() && "Not a type-id!");
1170
1171 OwningExprResult Result(Actions, true);
1172 CastTy = 0;
1173
1174 // We need to disambiguate a very ugly part of the C++ syntax:
1175 //
1176 // (T())x; - type-id
1177 // (T())*x; - type-id
1178 // (T())/x; - expression
1179 // (T()); - expression
1180 //
1181 // The bad news is that we cannot use the specialized tentative parser, since
1182 // it can only verify that the thing inside the parens can be parsed as
1183 // type-id, it is not useful for determining the context past the parens.
1184 //
1185 // The good news is that the parser can disambiguate this part without
Argyrios Kyrtzidis24ad6922009-05-22 15:12:46 +00001186 // making any unnecessary Action calls.
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001187 //
1188 // It uses a scheme similar to parsing inline methods. The parenthesized
1189 // tokens are cached, the context that follows is determined (possibly by
1190 // parsing a cast-expression), and then we re-introduce the cached tokens
1191 // into the token stream and parse them appropriately.
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001192
Mike Stump11289f42009-09-09 15:08:12 +00001193 ParenParseOption ParseAs;
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001194 CachedTokens Toks;
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001195
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001196 // Store the tokens of the parentheses. We will parse them after we determine
1197 // the context that follows them.
1198 if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
1199 // We didn't find the ')' we expected.
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001200 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1201 return ExprError();
1202 }
1203
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001204 if (Tok.is(tok::l_brace)) {
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001205 ParseAs = CompoundLiteral;
1206 } else {
1207 bool NotCastExpr;
Eli Friedmancf7530f2009-05-25 19:41:42 +00001208 // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
1209 if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
1210 NotCastExpr = true;
1211 } else {
1212 // Try parsing the cast-expression that may follow.
1213 // If it is not a cast-expression, NotCastExpr will be true and no token
1214 // will be consumed.
1215 Result = ParseCastExpression(false/*isUnaryExpression*/,
1216 false/*isAddressofOperand*/,
Nate Begeman5ec4b312009-08-10 23:49:36 +00001217 NotCastExpr, false);
Eli Friedmancf7530f2009-05-25 19:41:42 +00001218 }
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001219
1220 // If we parsed a cast-expression, it's really a type-id, otherwise it's
1221 // an expression.
1222 ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001223 }
1224
Mike Stump11289f42009-09-09 15:08:12 +00001225 // The current token should go after the cached tokens.
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001226 Toks.push_back(Tok);
1227 // Re-enter the stored parenthesized tokens into the token stream, so we may
1228 // parse them now.
1229 PP.EnterTokenStream(Toks.data(), Toks.size(),
1230 true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
1231 // Drop the current token and bring the first cached one. It's the same token
1232 // as when we entered this function.
1233 ConsumeAnyToken();
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001234
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001235 if (ParseAs >= CompoundLiteral) {
1236 TypeResult Ty = ParseTypeName();
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001237
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001238 // Match the ')'.
1239 if (Tok.is(tok::r_paren))
1240 RParenLoc = ConsumeParen();
1241 else
1242 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001243
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001244 if (ParseAs == CompoundLiteral) {
1245 ExprType = CompoundLiteral;
1246 return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
1247 }
Mike Stump11289f42009-09-09 15:08:12 +00001248
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001249 // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
1250 assert(ParseAs == CastExpr);
1251
1252 if (Ty.isInvalid())
1253 return ExprError();
1254
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001255 CastTy = Ty.get();
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001256
1257 // Result is what ParseCastExpression returned earlier.
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001258 if (!Result.isInvalid())
Mike Stump11289f42009-09-09 15:08:12 +00001259 Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
Nate Begeman5ec4b312009-08-10 23:49:36 +00001260 move(Result));
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001261 return move(Result);
1262 }
Mike Stump11289f42009-09-09 15:08:12 +00001263
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001264 // Not a compound literal, and not followed by a cast-expression.
1265 assert(ParseAs == SimpleExpr);
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001266
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001267 ExprType = SimpleExpr;
Argyrios Kyrtzidisf73f2d22009-05-22 21:09:47 +00001268 Result = ParseExpression();
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001269 if (!Result.isInvalid() && Tok.is(tok::r_paren))
1270 Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
1271
1272 // Match the ')'.
1273 if (Result.isInvalid()) {
1274 SkipUntil(tok::r_paren);
1275 return ExprError();
1276 }
Mike Stump11289f42009-09-09 15:08:12 +00001277
Argyrios Kyrtzidis12179bc2009-05-22 10:24:42 +00001278 if (Tok.is(tok::r_paren))
1279 RParenLoc = ConsumeParen();
1280 else
1281 MatchRHSPunctuation(tok::r_paren, LParenLoc);
1282
1283 return move(Result);
1284}