blob: 25aea352242a337106956862fc1121322cccec16 [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 Gregor52473432008-12-24 02:52:09 +0000231 if (TypeTy *DefaultType = ParseTypeName())
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000232 Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000233 }
234
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000235 return TypeParam;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000236}
237
238/// ParseTemplateTemplateParameter - Handle the parsing of template
239/// template parameters.
240///
241/// type-parameter: [C++ temp.param]
242/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
243/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Douglas Gregor52473432008-12-24 02:52:09 +0000244Parser::DeclTy *
245Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000246 assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
247
248 // Handle the template <...> part.
249 SourceLocation TemplateLoc = ConsumeToken();
Douglas Gregor52473432008-12-24 02:52:09 +0000250 TemplateParameterList TemplateParams;
Douglas Gregord406b032009-02-06 22:42:48 +0000251 SourceLocation LAngleLoc, RAngleLoc;
252 if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
253 RAngleLoc)) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000254 return 0;
255 }
256
257 // Generate a meaningful error if the user forgot to put class before the
258 // identifier, comma, or greater.
259 if(!Tok.is(tok::kw_class)) {
260 Diag(Tok.getLocation(), diag::err_expected_class_before)
261 << PP.getSpelling(Tok);
262 return 0;
263 }
264 SourceLocation ClassLoc = ConsumeToken();
265
266 // Get the identifier, if given.
Douglas Gregor279272e2009-02-04 19:02:06 +0000267 SourceLocation NameLoc;
268 IdentifierInfo* ParamName = 0;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000269 if(Tok.is(tok::identifier)) {
Douglas Gregor279272e2009-02-04 19:02:06 +0000270 ParamName = Tok.getIdentifierInfo();
271 NameLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000272 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
273 // Unnamed template parameter. Don't have to do anything here, just
274 // don't consume this token.
275 } else {
276 Diag(Tok.getLocation(), diag::err_expected_ident);
277 return 0;
278 }
279
280 // Get the a default value, if given.
Douglas Gregor279272e2009-02-04 19:02:06 +0000281 // FIXME: I think that the results of this block need to be passed to the
282 // act-on call, so we can assemble the parameter correctly.
Sebastian Redl62261042008-12-09 20:22:58 +0000283 OwningExprResult DefaultExpr(Actions);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000284 if(Tok.is(tok::equal)) {
285 ConsumeToken();
Sebastian Redlbb4dae72008-12-09 13:15:23 +0000286 DefaultExpr = ParseCXXIdExpression();
287 if(DefaultExpr.isInvalid()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000288 return 0;
289 }
290 }
291
Douglas Gregord406b032009-02-06 22:42:48 +0000292 TemplateParamsTy *ParamList =
293 Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
294 TemplateLoc, LAngleLoc,
295 &TemplateParams[0],
296 TemplateParams.size(),
297 RAngleLoc);
298
Douglas Gregor279272e2009-02-04 19:02:06 +0000299 return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
Douglas Gregord406b032009-02-06 22:42:48 +0000300 ParamList, ParamName,
Douglas Gregor279272e2009-02-04 19:02:06 +0000301 NameLoc, Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000302}
303
304/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
305/// template parameters (e.g., in "template<int Size> class array;").
Douglas Gregor2fa10442008-12-18 19:37:40 +0000306///
Douglas Gregorb3bec712008-12-01 23:54:00 +0000307/// template-parameter:
308/// ...
309/// parameter-declaration
310///
311/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
312/// but that didn't work out to well. Instead, this tries to recrate the basic
313/// parsing of parameter declarations, but tries to constrain it for template
314/// parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000315/// FIXME: We need to make a ParseParameterDeclaration that works for
316/// non-type template parameters and normal function parameters.
Douglas Gregor52473432008-12-24 02:52:09 +0000317Parser::DeclTy *
318Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000319 SourceLocation StartLoc = Tok.getLocation();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000320
321 // Parse the declaration-specifiers (i.e., the type).
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000322 // FIXME: The type should probably be restricted in some way... Not all
Douglas Gregorb3bec712008-12-01 23:54:00 +0000323 // declarators (parts of declarators?) are accepted for parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000324 DeclSpec DS;
325 ParseDeclarationSpecifiers(DS);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000326
327 // Parse this as a typename.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000328 Declarator ParamDecl(DS, Declarator::TemplateParamContext);
329 ParseDeclarator(ParamDecl);
Chris Lattner8376d2e2009-01-05 01:24:05 +0000330 if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000331 // This probably shouldn't happen - and it's more of a Sema thing, but
332 // basically we didn't parse the type name because we couldn't associate
333 // it with an AST node. we should just skip to the comma or greater.
334 // TODO: This is currently a placeholder for some kind of Sema Error.
335 Diag(Tok.getLocation(), diag::err_parse_error);
336 SkipUntil(tok::comma, tok::greater, true, true);
337 return 0;
338 }
339
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000340 // Create the parameter.
Douglas Gregor52473432008-12-24 02:52:09 +0000341 DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
342 Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000343
344 // Is there a default value? Parsing this can be fairly annoying because
345 // we have to stop on the first non-nested (paren'd) '>' as the closure
346 // for the template parameter list. Or a ','.
Chris Lattner8376d2e2009-01-05 01:24:05 +0000347 if (Tok.is(tok::equal)) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000348 // TODO: Implement default non-type values.
349 SkipUntil(tok::comma, tok::greater, true, true);
350 }
351
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000352 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000353}
Douglas Gregor2fa10442008-12-18 19:37:40 +0000354
355/// AnnotateTemplateIdToken - The current token is an identifier that
356/// refers to the template declaration Template, and is followed by a
357/// '<'. Turn this template-id into a template-id annotation token.
Douglas Gregor8e458f42009-02-09 18:46:07 +0000358void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
359 const CXXScopeSpec *SS) {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000360 assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
361 assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
362 "Parser isn't at the beginning of a template-id");
363
364 // Consume the template-name.
365 SourceLocation TemplateNameLoc = ConsumeToken();
366
367 // Consume the '<'.
368 SourceLocation LAngleLoc = ConsumeToken();
369
370 // Parse the optional template-argument-list.
Douglas Gregor6f37b582009-02-09 19:34:22 +0000371 TemplateArgList TemplateArgs;
372 TemplateArgIsTypeList TemplateArgIsType;
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000373 TemplateArgLocationList TemplateArgLocations;
374
Douglas Gregor8e458f42009-02-09 18:46:07 +0000375 {
Douglas Gregoraf0d0092009-02-09 21:04:56 +0000376 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
Douglas Gregor6f37b582009-02-09 19:34:22 +0000377 if (Tok.isNot(tok::greater) &&
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000378 ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType,
379 TemplateArgLocations)) {
Douglas Gregor8e458f42009-02-09 18:46:07 +0000380 // Try to find the closing '>'.
381 SkipUntil(tok::greater, true, true);
Douglas Gregoraf0d0092009-02-09 21:04:56 +0000382
383 // Clean up any template arguments that we successfully parsed.
384 ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
385 &TemplateArgIsType[0],
386 TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000387
Douglas Gregor8e458f42009-02-09 18:46:07 +0000388 return;
389 }
Douglas Gregor2fa10442008-12-18 19:37:40 +0000390 }
391
392 if (Tok.isNot(tok::greater))
393 return;
394
395 // Determine the location of the '>'. We won't actually consume this
396 // token, because we'll be replacing it with the template-id.
397 SourceLocation RAngleLoc = Tok.getLocation();
398
Douglas Gregor8e458f42009-02-09 18:46:07 +0000399 // Build the annotation token.
400 if (TNK == Action::TNK_Function_template) {
401 // This is a function template. We'll be building a template-id
402 // annotation token.
Douglas Gregor8e458f42009-02-09 18:46:07 +0000403 Tok.setKind(tok::annot_template_id);
404 TemplateIdAnnotation *TemplateId
405 = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
Douglas Gregor6f37b582009-02-09 19:34:22 +0000406 sizeof(void*) * TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000407 TemplateId->TemplateNameLoc = TemplateNameLoc;
408 TemplateId->Template = Template;
409 TemplateId->LAngleLoc = LAngleLoc;
410 TemplateId->NumArgs = TemplateArgs.size();
Douglas Gregor6f37b582009-02-09 19:34:22 +0000411 void **Args = (void**)(TemplateId + 1);
Douglas Gregor8e458f42009-02-09 18:46:07 +0000412 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
413 Args[Arg] = TemplateArgs[Arg];
414 Tok.setAnnotationValue(TemplateId);
415 } else {
416 // This is a type template, e.g., a class template, template
417 // template parameter, or template alias. We'll be building a
418 // "typename" annotation token.
Douglas Gregor6f37b582009-02-09 19:34:22 +0000419 ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
420 &TemplateArgIsType[0],
421 TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000422 TypeTy *Ty
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000423 = Actions.ActOnClassTemplateSpecialization(Template, TemplateNameLoc,
424 LAngleLoc, TemplateArgsPtr,
425 &TemplateArgLocations[0],
Douglas Gregor8e458f42009-02-09 18:46:07 +0000426 RAngleLoc, SS);
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000427
428 if (!Ty) // Something went wrong; don't annotate
429 return;
430
Douglas Gregor8e458f42009-02-09 18:46:07 +0000431 Tok.setKind(tok::annot_typename);
432 Tok.setAnnotationValue(Ty);
433 }
434
435 // Common fields for the annotation token
Douglas Gregor2fa10442008-12-18 19:37:40 +0000436 Tok.setAnnotationEndLoc(RAngleLoc);
437 Tok.setLocation(TemplateNameLoc);
438 if (SS && SS->isNotEmpty())
439 Tok.setLocation(SS->getBeginLoc());
440
Douglas Gregor2fa10442008-12-18 19:37:40 +0000441 // In case the tokens were cached, have Preprocessor replace them with the
442 // annotation token.
443 PP.AnnotateCachedTokens(Tok);
444}
445
446/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
447///
448/// template-argument: [C++ 14.2]
449/// assignment-expression
450/// type-id
451/// id-expression
Douglas Gregor6f37b582009-02-09 19:34:22 +0000452void *Parser::ParseTemplateArgument(bool &ArgIsType) {
Douglas Gregor8e458f42009-02-09 18:46:07 +0000453 // C++ [temp.arg]p2:
454 // In a template-argument, an ambiguity between a type-id and an
455 // expression is resolved to a type-id, regardless of the form of
456 // the corresponding template-parameter.
457 //
458 // Therefore, we initially try to parse a type-id.
Douglas Gregor341ac792009-02-10 00:53:15 +0000459 if (isCXXTypeId(TypeIdAsTemplateArgument)) {
Douglas Gregor6f37b582009-02-09 19:34:22 +0000460 ArgIsType = true;
461 return ParseTypeName();
Douglas Gregor8e458f42009-02-09 18:46:07 +0000462 }
463
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000464 OwningExprResult ExprArg = ParseAssignmentExpression();
465 if (ExprArg.isInvalid() || !ExprArg.get())
Douglas Gregor6f37b582009-02-09 19:34:22 +0000466 return 0;
Douglas Gregor8e458f42009-02-09 18:46:07 +0000467
Douglas Gregor6f37b582009-02-09 19:34:22 +0000468 ArgIsType = false;
469 return ExprArg.release();
Douglas Gregor2fa10442008-12-18 19:37:40 +0000470}
471
472/// ParseTemplateArgumentList - Parse a C++ template-argument-list
473/// (C++ [temp.names]). Returns true if there was an error.
474///
475/// template-argument-list: [C++ 14.2]
476/// template-argument
477/// template-argument-list ',' template-argument
Douglas Gregor6f37b582009-02-09 19:34:22 +0000478bool
479Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000480 TemplateArgIsTypeList &TemplateArgIsType,
481 TemplateArgLocationList &TemplateArgLocations) {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000482 while (true) {
Douglas Gregor6f37b582009-02-09 19:34:22 +0000483 bool IsType = false;
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000484 SourceLocation Loc = Tok.getLocation();
Douglas Gregor6f37b582009-02-09 19:34:22 +0000485 void *Arg = ParseTemplateArgument(IsType);
486 if (Arg) {
487 TemplateArgs.push_back(Arg);
488 TemplateArgIsType.push_back(IsType);
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000489 TemplateArgLocations.push_back(Loc);
Douglas Gregor6f37b582009-02-09 19:34:22 +0000490 } else {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000491 SkipUntil(tok::comma, tok::greater, true, true);
492 return true;
493 }
Douglas Gregor6f37b582009-02-09 19:34:22 +0000494
Douglas Gregor2fa10442008-12-18 19:37:40 +0000495 // If the next token is a comma, consume it and keep reading
496 // arguments.
497 if (Tok.isNot(tok::comma)) break;
498
499 // Consume the comma.
500 ConsumeToken();
501 }
502
503 return Tok.isNot(tok::greater);
504}
505