blob: 742453046b380586af74b1f2e75663513dc1bc28 [file] [log] [blame]
Douglas Gregorb3bec712008-12-01 23:54:00 +00001//===--- ParseTemplate.cpp - Template Parsing -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements parsing of C++ templates.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
Chris Lattner545f39e2009-01-29 05:15:15 +000015#include "clang/Parse/ParseDiagnostic.h"
Douglas Gregorb3bec712008-12-01 23:54:00 +000016#include "clang/Parse/DeclSpec.h"
17#include "clang/Parse/Scope.h"
Douglas Gregor8e458f42009-02-09 18:46:07 +000018#include "AstGuard.h"
Douglas Gregorb3bec712008-12-01 23:54:00 +000019
20using namespace clang;
21
22/// ParseTemplateDeclaration - Parse a template declaration, which includes
23/// the template parameter list and either a function of class declaration.
24///
25/// template-declaration: [C++ temp]
26/// 'export'[opt] 'template' '<' template-parameter-list '>' declaration
27Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) {
28 assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
29 "Token does not start a template declaration.");
30
Douglas Gregor8e7f9572008-12-02 00:41:28 +000031 // Enter template-parameter scope.
Douglas Gregor95d40792008-12-10 06:34:36 +000032 ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
Douglas Gregor8e7f9572008-12-02 00:41:28 +000033
Douglas Gregor52473432008-12-24 02:52:09 +000034 // Parse multiple levels of template headers within this template
35 // parameter scope, e.g.,
36 //
37 // template<typename T>
38 // template<typename U>
39 // class A<T>::B { ... };
40 //
41 // We parse multiple levels non-recursively so that we can build a
42 // single data structure containing all of the template parameter
Douglas Gregor279272e2009-02-04 19:02:06 +000043 // lists easily differentiate between the case above and:
Douglas Gregor52473432008-12-24 02:52:09 +000044 //
45 // template<typename T>
46 // class A {
47 // template<typename U> class B;
48 // };
49 //
50 // In the first case, the action for declaring A<T>::B receives
51 // both template parameter lists. In the second case, the action for
52 // defining A<T>::B receives just the inner template parameter list
53 // (and retrieves the outer template parameter list from its
54 // context).
55 TemplateParameterLists ParamLists;
56 do {
57 // Consume the 'export', if any.
58 SourceLocation ExportLoc;
59 if (Tok.is(tok::kw_export)) {
60 ExportLoc = ConsumeToken();
61 }
62
63 // Consume the 'template', which should be here.
64 SourceLocation TemplateLoc;
65 if (Tok.is(tok::kw_template)) {
66 TemplateLoc = ConsumeToken();
67 } else {
68 Diag(Tok.getLocation(), diag::err_expected_template);
69 return 0;
70 }
71
72 // Parse the '<' template-parameter-list '>'
73 SourceLocation LAngleLoc, RAngleLoc;
74 TemplateParameterList TemplateParams;
75 ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc,
76 RAngleLoc);
77
78 ParamLists.push_back(
79 Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc,
80 TemplateLoc, LAngleLoc,
81 &TemplateParams[0],
82 TemplateParams.size(), RAngleLoc));
83 } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
84
85 // Parse the actual template declaration.
Douglas Gregor279272e2009-02-04 19:02:06 +000086 return ParseDeclarationOrFunctionDefinition(&ParamLists);
Douglas Gregorb3bec712008-12-01 23:54:00 +000087}
88
89/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
Douglas Gregor279272e2009-02-04 19:02:06 +000090/// angle brackets. Depth is the depth of this template-parameter-list, which
91/// is the number of template headers directly enclosing this template header.
92/// TemplateParams is the current list of template parameters we're building.
93/// The template parameter we parse will be added to this list. LAngleLoc and
94/// RAngleLoc will receive the positions of the '<' and '>', respectively,
95/// that enclose this template parameter list.
Douglas Gregor52473432008-12-24 02:52:09 +000096bool Parser::ParseTemplateParameters(unsigned Depth,
97 TemplateParameterList &TemplateParams,
98 SourceLocation &LAngleLoc,
99 SourceLocation &RAngleLoc) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000100 // Get the template parameter list.
101 if(!Tok.is(tok::less)) {
102 Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
103 return false;
104 }
Douglas Gregor52473432008-12-24 02:52:09 +0000105 LAngleLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000106
107 // Try to parse the template parameter list.
Douglas Gregor52473432008-12-24 02:52:09 +0000108 if (Tok.is(tok::greater))
109 RAngleLoc = ConsumeToken();
110 else if(ParseTemplateParameterList(Depth, TemplateParams)) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000111 if(!Tok.is(tok::greater)) {
112 Diag(Tok.getLocation(), diag::err_expected_greater);
113 return false;
114 }
Douglas Gregor52473432008-12-24 02:52:09 +0000115 RAngleLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000116 }
117 return true;
118}
119
120/// ParseTemplateParameterList - Parse a template parameter list. If
121/// the parsing fails badly (i.e., closing bracket was left out), this
122/// will try to put the token stream in a reasonable position (closing
123/// a statement, etc.) and return false.
124///
125/// template-parameter-list: [C++ temp]
126/// template-parameter
127/// template-parameter-list ',' template-parameter
Douglas Gregor52473432008-12-24 02:52:09 +0000128bool
129Parser::ParseTemplateParameterList(unsigned Depth,
130 TemplateParameterList &TemplateParams) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000131 while(1) {
Douglas Gregor52473432008-12-24 02:52:09 +0000132 if (DeclTy* TmpParam
133 = ParseTemplateParameter(Depth, TemplateParams.size())) {
134 TemplateParams.push_back(TmpParam);
135 } else {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000136 // If we failed to parse a template parameter, skip until we find
137 // a comma or closing brace.
138 SkipUntil(tok::comma, tok::greater, true, true);
139 }
140
141 // Did we find a comma or the end of the template parmeter list?
142 if(Tok.is(tok::comma)) {
143 ConsumeToken();
144 } else if(Tok.is(tok::greater)) {
145 // Don't consume this... that's done by template parser.
146 break;
147 } else {
148 // Somebody probably forgot to close the template. Skip ahead and
149 // try to get out of the expression. This error is currently
150 // subsumed by whatever goes on in ParseTemplateParameter.
151 // TODO: This could match >>, and it would be nice to avoid those
152 // silly errors with template <vec<T>>.
153 // Diag(Tok.getLocation(), diag::err_expected_comma_greater);
154 SkipUntil(tok::greater, true, true);
155 return false;
156 }
157 }
158 return true;
159}
160
161/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
162///
163/// template-parameter: [C++ temp.param]
164/// type-parameter
165/// parameter-declaration
166///
167/// type-parameter: (see below)
168/// 'class' identifier[opt]
169/// 'class' identifier[opt] '=' type-id
170/// 'typename' identifier[opt]
171/// 'typename' identifier[opt] '=' type-id
172/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
173/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Douglas Gregor52473432008-12-24 02:52:09 +0000174Parser::DeclTy *
175Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
Chris Lattner4e7a4202009-01-04 23:51:17 +0000176 if(Tok.is(tok::kw_class) ||
177 (Tok.is(tok::kw_typename) &&
178 // FIXME: Next token has not been annotated!
Chris Lattner5d7eace2009-01-06 05:06:21 +0000179 NextToken().isNot(tok::annot_typename))) {
Douglas Gregor52473432008-12-24 02:52:09 +0000180 return ParseTypeParameter(Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000181 }
Chris Lattner4e7a4202009-01-04 23:51:17 +0000182
183 if(Tok.is(tok::kw_template))
184 return ParseTemplateTemplateParameter(Depth, Position);
185
186 // If it's none of the above, then it must be a parameter declaration.
187 // NOTE: This will pick up errors in the closure of the template parameter
188 // list (e.g., template < ; Check here to implement >> style closures.
189 return ParseNonTypeTemplateParameter(Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000190}
191
192/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
193/// Other kinds of template parameters are parsed in
194/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
195///
196/// type-parameter: [C++ temp.param]
197/// 'class' identifier[opt]
198/// 'class' identifier[opt] '=' type-id
199/// 'typename' identifier[opt]
200/// 'typename' identifier[opt] '=' type-id
Douglas Gregor52473432008-12-24 02:52:09 +0000201Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000202 assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
203 "A type-parameter starts with 'class' or 'typename'");
204
205 // Consume the 'class' or 'typename' keyword.
206 bool TypenameKeyword = Tok.is(tok::kw_typename);
207 SourceLocation KeyLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000208
209 // Grab the template parameter name (if given)
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000210 SourceLocation NameLoc;
211 IdentifierInfo* ParamName = 0;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000212 if(Tok.is(tok::identifier)) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000213 ParamName = Tok.getIdentifierInfo();
214 NameLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000215 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) ||
216 Tok.is(tok::greater)) {
217 // Unnamed template parameter. Don't have to do anything here, just
218 // don't consume this token.
219 } else {
220 Diag(Tok.getLocation(), diag::err_expected_ident);
221 return 0;
222 }
223
Douglas Gregor279272e2009-02-04 19:02:06 +0000224 DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
225 KeyLoc, ParamName, NameLoc,
Douglas Gregor52473432008-12-24 02:52:09 +0000226 Depth, Position);
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000227
Douglas Gregorb3bec712008-12-01 23:54:00 +0000228 // Grab a default type id (if given).
Douglas Gregorb3bec712008-12-01 23:54:00 +0000229 if(Tok.is(tok::equal)) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000230 SourceLocation EqualLoc = ConsumeToken();
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000231 SourceLocation DefaultLoc = Tok.getLocation();
Douglas Gregor52473432008-12-24 02:52:09 +0000232 if (TypeTy *DefaultType = ParseTypeName())
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000233 Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
234 DefaultType);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000235 }
236
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000237 return TypeParam;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000238}
239
240/// ParseTemplateTemplateParameter - Handle the parsing of template
241/// template parameters.
242///
243/// type-parameter: [C++ temp.param]
244/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
245/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Douglas Gregor52473432008-12-24 02:52:09 +0000246Parser::DeclTy *
247Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000248 assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
249
250 // Handle the template <...> part.
251 SourceLocation TemplateLoc = ConsumeToken();
Douglas Gregor52473432008-12-24 02:52:09 +0000252 TemplateParameterList TemplateParams;
Douglas Gregord406b032009-02-06 22:42:48 +0000253 SourceLocation LAngleLoc, RAngleLoc;
Douglas Gregor77f7ced2009-02-10 19:52:54 +0000254 {
255 ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
256 if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
257 RAngleLoc)) {
258 return 0;
259 }
Douglas Gregorb3bec712008-12-01 23:54:00 +0000260 }
261
262 // Generate a meaningful error if the user forgot to put class before the
263 // identifier, comma, or greater.
264 if(!Tok.is(tok::kw_class)) {
265 Diag(Tok.getLocation(), diag::err_expected_class_before)
266 << PP.getSpelling(Tok);
267 return 0;
268 }
269 SourceLocation ClassLoc = ConsumeToken();
270
271 // Get the identifier, if given.
Douglas Gregor279272e2009-02-04 19:02:06 +0000272 SourceLocation NameLoc;
273 IdentifierInfo* ParamName = 0;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000274 if(Tok.is(tok::identifier)) {
Douglas Gregor279272e2009-02-04 19:02:06 +0000275 ParamName = Tok.getIdentifierInfo();
276 NameLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000277 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
278 // Unnamed template parameter. Don't have to do anything here, just
279 // don't consume this token.
280 } else {
281 Diag(Tok.getLocation(), diag::err_expected_ident);
282 return 0;
283 }
284
Douglas Gregord406b032009-02-06 22:42:48 +0000285 TemplateParamsTy *ParamList =
286 Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
287 TemplateLoc, LAngleLoc,
288 &TemplateParams[0],
289 TemplateParams.size(),
290 RAngleLoc);
291
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000292 Parser::DeclTy * Param
293 = Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
294 ParamList, ParamName,
295 NameLoc, Depth, Position);
296
297 // Get the a default value, if given.
298 if (Tok.is(tok::equal)) {
299 SourceLocation EqualLoc = ConsumeToken();
300 OwningExprResult DefaultExpr = ParseCXXIdExpression();
301 if (DefaultExpr.isInvalid())
302 return Param;
303 else if (Param)
304 Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
305 move(DefaultExpr));
306 }
307
308 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000309}
310
311/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
312/// template parameters (e.g., in "template<int Size> class array;").
Douglas Gregor2fa10442008-12-18 19:37:40 +0000313///
Douglas Gregorb3bec712008-12-01 23:54:00 +0000314/// template-parameter:
315/// ...
316/// parameter-declaration
317///
318/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
319/// but that didn't work out to well. Instead, this tries to recrate the basic
320/// parsing of parameter declarations, but tries to constrain it for template
321/// parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000322/// FIXME: We need to make a ParseParameterDeclaration that works for
323/// non-type template parameters and normal function parameters.
Douglas Gregor52473432008-12-24 02:52:09 +0000324Parser::DeclTy *
325Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000326 SourceLocation StartLoc = Tok.getLocation();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000327
328 // Parse the declaration-specifiers (i.e., the type).
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000329 // FIXME: The type should probably be restricted in some way... Not all
Douglas Gregorb3bec712008-12-01 23:54:00 +0000330 // declarators (parts of declarators?) are accepted for parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000331 DeclSpec DS;
332 ParseDeclarationSpecifiers(DS);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000333
334 // Parse this as a typename.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000335 Declarator ParamDecl(DS, Declarator::TemplateParamContext);
336 ParseDeclarator(ParamDecl);
Chris Lattner8376d2e2009-01-05 01:24:05 +0000337 if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000338 // This probably shouldn't happen - and it's more of a Sema thing, but
339 // basically we didn't parse the type name because we couldn't associate
340 // it with an AST node. we should just skip to the comma or greater.
341 // TODO: This is currently a placeholder for some kind of Sema Error.
342 Diag(Tok.getLocation(), diag::err_parse_error);
343 SkipUntil(tok::comma, tok::greater, true, true);
344 return 0;
345 }
346
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000347 // Create the parameter.
Douglas Gregor52473432008-12-24 02:52:09 +0000348 DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
349 Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000350
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000351 // If there is a default value, parse it.
Chris Lattner8376d2e2009-01-05 01:24:05 +0000352 if (Tok.is(tok::equal)) {
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000353 SourceLocation EqualLoc = ConsumeToken();
354
355 // C++ [temp.param]p15:
356 // When parsing a default template-argument for a non-type
357 // template-parameter, the first non-nested > is taken as the
358 // end of the template-parameter-list rather than a greater-than
359 // operator.
360 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
361
362 OwningExprResult DefaultArg = ParseAssignmentExpression();
363 if (DefaultArg.isInvalid())
364 SkipUntil(tok::comma, tok::greater, true, true);
365 else if (Param)
366 Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
367 move(DefaultArg));
Douglas Gregorb3bec712008-12-01 23:54:00 +0000368 }
369
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000370 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000371}
Douglas Gregor2fa10442008-12-18 19:37:40 +0000372
373/// AnnotateTemplateIdToken - The current token is an identifier that
374/// refers to the template declaration Template, and is followed by a
375/// '<'. Turn this template-id into a template-id annotation token.
Douglas Gregor8e458f42009-02-09 18:46:07 +0000376void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
377 const CXXScopeSpec *SS) {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000378 assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
379 assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
380 "Parser isn't at the beginning of a template-id");
381
382 // Consume the template-name.
383 SourceLocation TemplateNameLoc = ConsumeToken();
384
385 // Consume the '<'.
386 SourceLocation LAngleLoc = ConsumeToken();
387
388 // Parse the optional template-argument-list.
Douglas Gregor6f37b582009-02-09 19:34:22 +0000389 TemplateArgList TemplateArgs;
390 TemplateArgIsTypeList TemplateArgIsType;
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000391 TemplateArgLocationList TemplateArgLocations;
392
Douglas Gregor8e458f42009-02-09 18:46:07 +0000393 {
Douglas Gregoraf0d0092009-02-09 21:04:56 +0000394 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
Douglas Gregor6f37b582009-02-09 19:34:22 +0000395 if (Tok.isNot(tok::greater) &&
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000396 ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType,
397 TemplateArgLocations)) {
Douglas Gregor8e458f42009-02-09 18:46:07 +0000398 // Try to find the closing '>'.
399 SkipUntil(tok::greater, true, true);
Douglas Gregoraf0d0092009-02-09 21:04:56 +0000400
401 // Clean up any template arguments that we successfully parsed.
402 ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
403 &TemplateArgIsType[0],
404 TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000405
Douglas Gregor8e458f42009-02-09 18:46:07 +0000406 return;
407 }
Douglas Gregor2fa10442008-12-18 19:37:40 +0000408 }
409
410 if (Tok.isNot(tok::greater))
411 return;
412
413 // Determine the location of the '>'. We won't actually consume this
414 // token, because we'll be replacing it with the template-id.
415 SourceLocation RAngleLoc = Tok.getLocation();
416
Douglas Gregor8e458f42009-02-09 18:46:07 +0000417 // Build the annotation token.
418 if (TNK == Action::TNK_Function_template) {
419 // This is a function template. We'll be building a template-id
420 // annotation token.
Douglas Gregor8e458f42009-02-09 18:46:07 +0000421 Tok.setKind(tok::annot_template_id);
422 TemplateIdAnnotation *TemplateId
423 = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
Douglas Gregor6f37b582009-02-09 19:34:22 +0000424 sizeof(void*) * TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000425 TemplateId->TemplateNameLoc = TemplateNameLoc;
426 TemplateId->Template = Template;
427 TemplateId->LAngleLoc = LAngleLoc;
428 TemplateId->NumArgs = TemplateArgs.size();
Douglas Gregor6f37b582009-02-09 19:34:22 +0000429 void **Args = (void**)(TemplateId + 1);
Douglas Gregor8e458f42009-02-09 18:46:07 +0000430 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
431 Args[Arg] = TemplateArgs[Arg];
432 Tok.setAnnotationValue(TemplateId);
433 } else {
434 // This is a type template, e.g., a class template, template
435 // template parameter, or template alias. We'll be building a
436 // "typename" annotation token.
Douglas Gregor6f37b582009-02-09 19:34:22 +0000437 ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
438 &TemplateArgIsType[0],
439 TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000440 TypeTy *Ty
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000441 = Actions.ActOnClassTemplateSpecialization(Template, TemplateNameLoc,
442 LAngleLoc, TemplateArgsPtr,
443 &TemplateArgLocations[0],
Douglas Gregor8e458f42009-02-09 18:46:07 +0000444 RAngleLoc, SS);
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000445
446 if (!Ty) // Something went wrong; don't annotate
447 return;
448
Douglas Gregor8e458f42009-02-09 18:46:07 +0000449 Tok.setKind(tok::annot_typename);
450 Tok.setAnnotationValue(Ty);
451 }
452
453 // Common fields for the annotation token
Douglas Gregor2fa10442008-12-18 19:37:40 +0000454 Tok.setAnnotationEndLoc(RAngleLoc);
455 Tok.setLocation(TemplateNameLoc);
456 if (SS && SS->isNotEmpty())
457 Tok.setLocation(SS->getBeginLoc());
458
Douglas Gregor2fa10442008-12-18 19:37:40 +0000459 // In case the tokens were cached, have Preprocessor replace them with the
460 // annotation token.
461 PP.AnnotateCachedTokens(Tok);
462}
463
464/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
465///
466/// template-argument: [C++ 14.2]
467/// assignment-expression
468/// type-id
469/// id-expression
Douglas Gregor6f37b582009-02-09 19:34:22 +0000470void *Parser::ParseTemplateArgument(bool &ArgIsType) {
Douglas Gregor8e458f42009-02-09 18:46:07 +0000471 // C++ [temp.arg]p2:
472 // In a template-argument, an ambiguity between a type-id and an
473 // expression is resolved to a type-id, regardless of the form of
474 // the corresponding template-parameter.
475 //
476 // Therefore, we initially try to parse a type-id.
Douglas Gregor341ac792009-02-10 00:53:15 +0000477 if (isCXXTypeId(TypeIdAsTemplateArgument)) {
Douglas Gregor6f37b582009-02-09 19:34:22 +0000478 ArgIsType = true;
479 return ParseTypeName();
Douglas Gregor8e458f42009-02-09 18:46:07 +0000480 }
481
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000482 OwningExprResult ExprArg = ParseAssignmentExpression();
483 if (ExprArg.isInvalid() || !ExprArg.get())
Douglas Gregor6f37b582009-02-09 19:34:22 +0000484 return 0;
Douglas Gregor8e458f42009-02-09 18:46:07 +0000485
Douglas Gregor6f37b582009-02-09 19:34:22 +0000486 ArgIsType = false;
487 return ExprArg.release();
Douglas Gregor2fa10442008-12-18 19:37:40 +0000488}
489
490/// ParseTemplateArgumentList - Parse a C++ template-argument-list
491/// (C++ [temp.names]). Returns true if there was an error.
492///
493/// template-argument-list: [C++ 14.2]
494/// template-argument
495/// template-argument-list ',' template-argument
Douglas Gregor6f37b582009-02-09 19:34:22 +0000496bool
497Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000498 TemplateArgIsTypeList &TemplateArgIsType,
499 TemplateArgLocationList &TemplateArgLocations) {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000500 while (true) {
Douglas Gregor6f37b582009-02-09 19:34:22 +0000501 bool IsType = false;
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000502 SourceLocation Loc = Tok.getLocation();
Douglas Gregor6f37b582009-02-09 19:34:22 +0000503 void *Arg = ParseTemplateArgument(IsType);
504 if (Arg) {
505 TemplateArgs.push_back(Arg);
506 TemplateArgIsType.push_back(IsType);
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000507 TemplateArgLocations.push_back(Loc);
Douglas Gregor6f37b582009-02-09 19:34:22 +0000508 } else {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000509 SkipUntil(tok::comma, tok::greater, true, true);
510 return true;
511 }
Douglas Gregor6f37b582009-02-09 19:34:22 +0000512
Douglas Gregor2fa10442008-12-18 19:37:40 +0000513 // If the next token is a comma, consume it and keep reading
514 // arguments.
515 if (Tok.isNot(tok::comma)) break;
516
517 // Consume the comma.
518 ConsumeToken();
519 }
520
521 return Tok.isNot(tok::greater);
522}
523