blob: d17d2445351a9d866775a734c19d8947948f5ce2 [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;
254 if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
255 RAngleLoc)) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000256 return 0;
257 }
258
259 // Generate a meaningful error if the user forgot to put class before the
260 // identifier, comma, or greater.
261 if(!Tok.is(tok::kw_class)) {
262 Diag(Tok.getLocation(), diag::err_expected_class_before)
263 << PP.getSpelling(Tok);
264 return 0;
265 }
266 SourceLocation ClassLoc = ConsumeToken();
267
268 // Get the identifier, if given.
Douglas Gregor279272e2009-02-04 19:02:06 +0000269 SourceLocation NameLoc;
270 IdentifierInfo* ParamName = 0;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000271 if(Tok.is(tok::identifier)) {
Douglas Gregor279272e2009-02-04 19:02:06 +0000272 ParamName = Tok.getIdentifierInfo();
273 NameLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000274 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
275 // Unnamed template parameter. Don't have to do anything here, just
276 // don't consume this token.
277 } else {
278 Diag(Tok.getLocation(), diag::err_expected_ident);
279 return 0;
280 }
281
Douglas Gregord406b032009-02-06 22:42:48 +0000282 TemplateParamsTy *ParamList =
283 Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
284 TemplateLoc, LAngleLoc,
285 &TemplateParams[0],
286 TemplateParams.size(),
287 RAngleLoc);
288
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000289 Parser::DeclTy * Param
290 = Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
291 ParamList, ParamName,
292 NameLoc, Depth, Position);
293
294 // Get the a default value, if given.
295 if (Tok.is(tok::equal)) {
296 SourceLocation EqualLoc = ConsumeToken();
297 OwningExprResult DefaultExpr = ParseCXXIdExpression();
298 if (DefaultExpr.isInvalid())
299 return Param;
300 else if (Param)
301 Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
302 move(DefaultExpr));
303 }
304
305 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000306}
307
308/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
309/// template parameters (e.g., in "template<int Size> class array;").
Douglas Gregor2fa10442008-12-18 19:37:40 +0000310///
Douglas Gregorb3bec712008-12-01 23:54:00 +0000311/// template-parameter:
312/// ...
313/// parameter-declaration
314///
315/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
316/// but that didn't work out to well. Instead, this tries to recrate the basic
317/// parsing of parameter declarations, but tries to constrain it for template
318/// parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000319/// FIXME: We need to make a ParseParameterDeclaration that works for
320/// non-type template parameters and normal function parameters.
Douglas Gregor52473432008-12-24 02:52:09 +0000321Parser::DeclTy *
322Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000323 SourceLocation StartLoc = Tok.getLocation();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000324
325 // Parse the declaration-specifiers (i.e., the type).
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000326 // FIXME: The type should probably be restricted in some way... Not all
Douglas Gregorb3bec712008-12-01 23:54:00 +0000327 // declarators (parts of declarators?) are accepted for parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000328 DeclSpec DS;
329 ParseDeclarationSpecifiers(DS);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000330
331 // Parse this as a typename.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000332 Declarator ParamDecl(DS, Declarator::TemplateParamContext);
333 ParseDeclarator(ParamDecl);
Chris Lattner8376d2e2009-01-05 01:24:05 +0000334 if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000335 // This probably shouldn't happen - and it's more of a Sema thing, but
336 // basically we didn't parse the type name because we couldn't associate
337 // it with an AST node. we should just skip to the comma or greater.
338 // TODO: This is currently a placeholder for some kind of Sema Error.
339 Diag(Tok.getLocation(), diag::err_parse_error);
340 SkipUntil(tok::comma, tok::greater, true, true);
341 return 0;
342 }
343
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000344 // Create the parameter.
Douglas Gregor52473432008-12-24 02:52:09 +0000345 DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
346 Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000347
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000348 // If there is a default value, parse it.
Chris Lattner8376d2e2009-01-05 01:24:05 +0000349 if (Tok.is(tok::equal)) {
Douglas Gregor9225a7e2009-02-10 19:49:53 +0000350 SourceLocation EqualLoc = ConsumeToken();
351
352 // C++ [temp.param]p15:
353 // When parsing a default template-argument for a non-type
354 // template-parameter, the first non-nested > is taken as the
355 // end of the template-parameter-list rather than a greater-than
356 // operator.
357 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
358
359 OwningExprResult DefaultArg = ParseAssignmentExpression();
360 if (DefaultArg.isInvalid())
361 SkipUntil(tok::comma, tok::greater, true, true);
362 else if (Param)
363 Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
364 move(DefaultArg));
Douglas Gregorb3bec712008-12-01 23:54:00 +0000365 }
366
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000367 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000368}
Douglas Gregor2fa10442008-12-18 19:37:40 +0000369
370/// AnnotateTemplateIdToken - The current token is an identifier that
371/// refers to the template declaration Template, and is followed by a
372/// '<'. Turn this template-id into a template-id annotation token.
Douglas Gregor8e458f42009-02-09 18:46:07 +0000373void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
374 const CXXScopeSpec *SS) {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000375 assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
376 assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
377 "Parser isn't at the beginning of a template-id");
378
379 // Consume the template-name.
380 SourceLocation TemplateNameLoc = ConsumeToken();
381
382 // Consume the '<'.
383 SourceLocation LAngleLoc = ConsumeToken();
384
385 // Parse the optional template-argument-list.
Douglas Gregor6f37b582009-02-09 19:34:22 +0000386 TemplateArgList TemplateArgs;
387 TemplateArgIsTypeList TemplateArgIsType;
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000388 TemplateArgLocationList TemplateArgLocations;
389
Douglas Gregor8e458f42009-02-09 18:46:07 +0000390 {
Douglas Gregoraf0d0092009-02-09 21:04:56 +0000391 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
Douglas Gregor6f37b582009-02-09 19:34:22 +0000392 if (Tok.isNot(tok::greater) &&
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000393 ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType,
394 TemplateArgLocations)) {
Douglas Gregor8e458f42009-02-09 18:46:07 +0000395 // Try to find the closing '>'.
396 SkipUntil(tok::greater, true, true);
Douglas Gregoraf0d0092009-02-09 21:04:56 +0000397
398 // Clean up any template arguments that we successfully parsed.
399 ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
400 &TemplateArgIsType[0],
401 TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000402
Douglas Gregor8e458f42009-02-09 18:46:07 +0000403 return;
404 }
Douglas Gregor2fa10442008-12-18 19:37:40 +0000405 }
406
407 if (Tok.isNot(tok::greater))
408 return;
409
410 // Determine the location of the '>'. We won't actually consume this
411 // token, because we'll be replacing it with the template-id.
412 SourceLocation RAngleLoc = Tok.getLocation();
413
Douglas Gregor8e458f42009-02-09 18:46:07 +0000414 // Build the annotation token.
415 if (TNK == Action::TNK_Function_template) {
416 // This is a function template. We'll be building a template-id
417 // annotation token.
Douglas Gregor8e458f42009-02-09 18:46:07 +0000418 Tok.setKind(tok::annot_template_id);
419 TemplateIdAnnotation *TemplateId
420 = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
Douglas Gregor6f37b582009-02-09 19:34:22 +0000421 sizeof(void*) * TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000422 TemplateId->TemplateNameLoc = TemplateNameLoc;
423 TemplateId->Template = Template;
424 TemplateId->LAngleLoc = LAngleLoc;
425 TemplateId->NumArgs = TemplateArgs.size();
Douglas Gregor6f37b582009-02-09 19:34:22 +0000426 void **Args = (void**)(TemplateId + 1);
Douglas Gregor8e458f42009-02-09 18:46:07 +0000427 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
428 Args[Arg] = TemplateArgs[Arg];
429 Tok.setAnnotationValue(TemplateId);
430 } else {
431 // This is a type template, e.g., a class template, template
432 // template parameter, or template alias. We'll be building a
433 // "typename" annotation token.
Douglas Gregor6f37b582009-02-09 19:34:22 +0000434 ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
435 &TemplateArgIsType[0],
436 TemplateArgs.size());
Douglas Gregor8e458f42009-02-09 18:46:07 +0000437 TypeTy *Ty
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000438 = Actions.ActOnClassTemplateSpecialization(Template, TemplateNameLoc,
439 LAngleLoc, TemplateArgsPtr,
440 &TemplateArgLocations[0],
Douglas Gregor8e458f42009-02-09 18:46:07 +0000441 RAngleLoc, SS);
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000442
443 if (!Ty) // Something went wrong; don't annotate
444 return;
445
Douglas Gregor8e458f42009-02-09 18:46:07 +0000446 Tok.setKind(tok::annot_typename);
447 Tok.setAnnotationValue(Ty);
448 }
449
450 // Common fields for the annotation token
Douglas Gregor2fa10442008-12-18 19:37:40 +0000451 Tok.setAnnotationEndLoc(RAngleLoc);
452 Tok.setLocation(TemplateNameLoc);
453 if (SS && SS->isNotEmpty())
454 Tok.setLocation(SS->getBeginLoc());
455
Douglas Gregor2fa10442008-12-18 19:37:40 +0000456 // In case the tokens were cached, have Preprocessor replace them with the
457 // annotation token.
458 PP.AnnotateCachedTokens(Tok);
459}
460
461/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
462///
463/// template-argument: [C++ 14.2]
464/// assignment-expression
465/// type-id
466/// id-expression
Douglas Gregor6f37b582009-02-09 19:34:22 +0000467void *Parser::ParseTemplateArgument(bool &ArgIsType) {
Douglas Gregor8e458f42009-02-09 18:46:07 +0000468 // C++ [temp.arg]p2:
469 // In a template-argument, an ambiguity between a type-id and an
470 // expression is resolved to a type-id, regardless of the form of
471 // the corresponding template-parameter.
472 //
473 // Therefore, we initially try to parse a type-id.
Douglas Gregor341ac792009-02-10 00:53:15 +0000474 if (isCXXTypeId(TypeIdAsTemplateArgument)) {
Douglas Gregor6f37b582009-02-09 19:34:22 +0000475 ArgIsType = true;
476 return ParseTypeName();
Douglas Gregor8e458f42009-02-09 18:46:07 +0000477 }
478
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000479 OwningExprResult ExprArg = ParseAssignmentExpression();
480 if (ExprArg.isInvalid() || !ExprArg.get())
Douglas Gregor6f37b582009-02-09 19:34:22 +0000481 return 0;
Douglas Gregor8e458f42009-02-09 18:46:07 +0000482
Douglas Gregor6f37b582009-02-09 19:34:22 +0000483 ArgIsType = false;
484 return ExprArg.release();
Douglas Gregor2fa10442008-12-18 19:37:40 +0000485}
486
487/// ParseTemplateArgumentList - Parse a C++ template-argument-list
488/// (C++ [temp.names]). Returns true if there was an error.
489///
490/// template-argument-list: [C++ 14.2]
491/// template-argument
492/// template-argument-list ',' template-argument
Douglas Gregor6f37b582009-02-09 19:34:22 +0000493bool
494Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000495 TemplateArgIsTypeList &TemplateArgIsType,
496 TemplateArgLocationList &TemplateArgLocations) {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000497 while (true) {
Douglas Gregor6f37b582009-02-09 19:34:22 +0000498 bool IsType = false;
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000499 SourceLocation Loc = Tok.getLocation();
Douglas Gregor6f37b582009-02-09 19:34:22 +0000500 void *Arg = ParseTemplateArgument(IsType);
501 if (Arg) {
502 TemplateArgs.push_back(Arg);
503 TemplateArgIsType.push_back(IsType);
Douglas Gregor35d81bb2009-02-09 23:23:08 +0000504 TemplateArgLocations.push_back(Loc);
Douglas Gregor6f37b582009-02-09 19:34:22 +0000505 } else {
Douglas Gregor2fa10442008-12-18 19:37:40 +0000506 SkipUntil(tok::comma, tok::greater, true, true);
507 return true;
508 }
Douglas Gregor6f37b582009-02-09 19:34:22 +0000509
Douglas Gregor2fa10442008-12-18 19:37:40 +0000510 // If the next token is a comma, consume it and keep reading
511 // arguments.
512 if (Tok.isNot(tok::comma)) break;
513
514 // Consume the comma.
515 ConsumeToken();
516 }
517
518 return Tok.isNot(tok::greater);
519}
520