blob: ed5e22401e7532455cde499ba9b3b1d0a7c1cc1d [file] [log] [blame]
Douglas Gregoradcac882008-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"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/Parse/DeclSpec.h"
17#include "clang/Parse/Scope.h"
18
19using namespace clang;
20
21/// ParseTemplateDeclaration - Parse a template declaration, which includes
22/// the template parameter list and either a function of class declaration.
23///
24/// template-declaration: [C++ temp]
25/// 'export'[opt] 'template' '<' template-parameter-list '>' declaration
26Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) {
27 assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
28 "Token does not start a template declaration.");
29
Douglas Gregor26236e82008-12-02 00:41:28 +000030 // Enter template-parameter scope.
Douglas Gregor8935b8b2008-12-10 06:34:36 +000031 ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
Douglas Gregor26236e82008-12-02 00:41:28 +000032
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +000033 // Parse multiple levels of template headers within this template
34 // parameter scope, e.g.,
35 //
36 // template<typename T>
37 // template<typename U>
38 // class A<T>::B { ... };
39 //
40 // We parse multiple levels non-recursively so that we can build a
41 // single data structure containing all of the template parameter
42 // lists, and easily differentiate between the case above and:
43 //
44 // template<typename T>
45 // class A {
46 // template<typename U> class B;
47 // };
48 //
49 // In the first case, the action for declaring A<T>::B receives
50 // both template parameter lists. In the second case, the action for
51 // defining A<T>::B receives just the inner template parameter list
52 // (and retrieves the outer template parameter list from its
53 // context).
54 TemplateParameterLists ParamLists;
55 do {
56 // Consume the 'export', if any.
57 SourceLocation ExportLoc;
58 if (Tok.is(tok::kw_export)) {
59 ExportLoc = ConsumeToken();
60 }
61
62 // Consume the 'template', which should be here.
63 SourceLocation TemplateLoc;
64 if (Tok.is(tok::kw_template)) {
65 TemplateLoc = ConsumeToken();
66 } else {
67 Diag(Tok.getLocation(), diag::err_expected_template);
68 return 0;
69 }
70
71 // Parse the '<' template-parameter-list '>'
72 SourceLocation LAngleLoc, RAngleLoc;
73 TemplateParameterList TemplateParams;
74 ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc,
75 RAngleLoc);
76
77 ParamLists.push_back(
78 Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc,
79 TemplateLoc, LAngleLoc,
80 &TemplateParams[0],
81 TemplateParams.size(), RAngleLoc));
82 } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
83
84 // Parse the actual template declaration.
85 DeclTy *TemplateDecl = ParseDeclarationOrFunctionDefinition(&ParamLists);
Douglas Gregor26236e82008-12-02 00:41:28 +000086
Douglas Gregor26236e82008-12-02 00:41:28 +000087 return TemplateDecl;
Douglas Gregoradcac882008-12-01 23:54:00 +000088}
89
90/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +000091/// angle brackets. Depth is the depth of this
92/// template-parameter-list, which is the number of template headers
93/// directly enclosing this template header. TemplateParams is the
94/// current list of template parameters we're building. The template
95/// parameter we parse will be added to this list. LAngleLoc and
96/// RAngleLoc will receive the positions of the '<' and '>',
97/// respectively, that enclose this template parameter list.
98bool Parser::ParseTemplateParameters(unsigned Depth,
99 TemplateParameterList &TemplateParams,
100 SourceLocation &LAngleLoc,
101 SourceLocation &RAngleLoc) {
Douglas Gregoradcac882008-12-01 23:54:00 +0000102 // Get the template parameter list.
103 if(!Tok.is(tok::less)) {
104 Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
105 return false;
106 }
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000107 LAngleLoc = ConsumeToken();
Douglas Gregoradcac882008-12-01 23:54:00 +0000108
109 // Try to parse the template parameter list.
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000110 if (Tok.is(tok::greater))
111 RAngleLoc = ConsumeToken();
112 else if(ParseTemplateParameterList(Depth, TemplateParams)) {
Douglas Gregoradcac882008-12-01 23:54:00 +0000113 if(!Tok.is(tok::greater)) {
114 Diag(Tok.getLocation(), diag::err_expected_greater);
115 return false;
116 }
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000117 RAngleLoc = ConsumeToken();
Douglas Gregoradcac882008-12-01 23:54:00 +0000118 }
119 return true;
120}
121
122/// ParseTemplateParameterList - Parse a template parameter list. If
123/// the parsing fails badly (i.e., closing bracket was left out), this
124/// will try to put the token stream in a reasonable position (closing
125/// a statement, etc.) and return false.
126///
127/// template-parameter-list: [C++ temp]
128/// template-parameter
129/// template-parameter-list ',' template-parameter
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000130bool
131Parser::ParseTemplateParameterList(unsigned Depth,
132 TemplateParameterList &TemplateParams) {
Douglas Gregoradcac882008-12-01 23:54:00 +0000133 while(1) {
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000134 if (DeclTy* TmpParam
135 = ParseTemplateParameter(Depth, TemplateParams.size())) {
136 TemplateParams.push_back(TmpParam);
137 } else {
Douglas Gregoradcac882008-12-01 23:54:00 +0000138 // If we failed to parse a template parameter, skip until we find
139 // a comma or closing brace.
140 SkipUntil(tok::comma, tok::greater, true, true);
141 }
142
143 // Did we find a comma or the end of the template parmeter list?
144 if(Tok.is(tok::comma)) {
145 ConsumeToken();
146 } else if(Tok.is(tok::greater)) {
147 // Don't consume this... that's done by template parser.
148 break;
149 } else {
150 // Somebody probably forgot to close the template. Skip ahead and
151 // try to get out of the expression. This error is currently
152 // subsumed by whatever goes on in ParseTemplateParameter.
153 // TODO: This could match >>, and it would be nice to avoid those
154 // silly errors with template <vec<T>>.
155 // Diag(Tok.getLocation(), diag::err_expected_comma_greater);
156 SkipUntil(tok::greater, true, true);
157 return false;
158 }
159 }
160 return true;
161}
162
163/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
164///
165/// template-parameter: [C++ temp.param]
166/// type-parameter
167/// parameter-declaration
168///
169/// type-parameter: (see below)
170/// 'class' identifier[opt]
171/// 'class' identifier[opt] '=' type-id
172/// 'typename' identifier[opt]
173/// 'typename' identifier[opt] '=' type-id
174/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
175/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000176Parser::DeclTy *
177Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
Chris Lattner532e19b2009-01-04 23:51:17 +0000178 if(Tok.is(tok::kw_class) ||
179 (Tok.is(tok::kw_typename) &&
180 // FIXME: Next token has not been annotated!
Chris Lattnerb31757b2009-01-06 05:06:21 +0000181 NextToken().isNot(tok::annot_typename))) {
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000182 return ParseTypeParameter(Depth, Position);
Douglas Gregoradcac882008-12-01 23:54:00 +0000183 }
Chris Lattner532e19b2009-01-04 23:51:17 +0000184
185 if(Tok.is(tok::kw_template))
186 return ParseTemplateTemplateParameter(Depth, Position);
187
188 // If it's none of the above, then it must be a parameter declaration.
189 // NOTE: This will pick up errors in the closure of the template parameter
190 // list (e.g., template < ; Check here to implement >> style closures.
191 return ParseNonTypeTemplateParameter(Depth, Position);
Douglas Gregoradcac882008-12-01 23:54:00 +0000192}
193
194/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
195/// Other kinds of template parameters are parsed in
196/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
197///
198/// type-parameter: [C++ temp.param]
199/// 'class' identifier[opt]
200/// 'class' identifier[opt] '=' type-id
201/// 'typename' identifier[opt]
202/// 'typename' identifier[opt] '=' type-id
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000203Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
Douglas Gregor26236e82008-12-02 00:41:28 +0000204 assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
205 "A type-parameter starts with 'class' or 'typename'");
206
207 // Consume the 'class' or 'typename' keyword.
208 bool TypenameKeyword = Tok.is(tok::kw_typename);
209 SourceLocation KeyLoc = ConsumeToken();
Douglas Gregoradcac882008-12-01 23:54:00 +0000210
211 // Grab the template parameter name (if given)
Douglas Gregor26236e82008-12-02 00:41:28 +0000212 SourceLocation NameLoc;
213 IdentifierInfo* ParamName = 0;
Douglas Gregoradcac882008-12-01 23:54:00 +0000214 if(Tok.is(tok::identifier)) {
Douglas Gregor26236e82008-12-02 00:41:28 +0000215 ParamName = Tok.getIdentifierInfo();
216 NameLoc = ConsumeToken();
Douglas Gregoradcac882008-12-01 23:54:00 +0000217 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) ||
218 Tok.is(tok::greater)) {
219 // Unnamed template parameter. Don't have to do anything here, just
220 // don't consume this token.
221 } else {
222 Diag(Tok.getLocation(), diag::err_expected_ident);
223 return 0;
224 }
225
Douglas Gregor26236e82008-12-02 00:41:28 +0000226 DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000227 KeyLoc, ParamName, NameLoc,
228 Depth, Position);
Douglas Gregor26236e82008-12-02 00:41:28 +0000229
Douglas Gregoradcac882008-12-01 23:54:00 +0000230 // Grab a default type id (if given).
Douglas Gregoradcac882008-12-01 23:54:00 +0000231 if(Tok.is(tok::equal)) {
Douglas Gregor26236e82008-12-02 00:41:28 +0000232 SourceLocation EqualLoc = ConsumeToken();
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000233 if (TypeTy *DefaultType = ParseTypeName())
Douglas Gregor26236e82008-12-02 00:41:28 +0000234 Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
Douglas Gregoradcac882008-12-01 23:54:00 +0000235 }
236
Douglas Gregor26236e82008-12-02 00:41:28 +0000237 return TypeParam;
Douglas Gregoradcac882008-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 Gregorc4b4e7b2008-12-24 02:52:09 +0000246Parser::DeclTy *
247Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregoradcac882008-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 Gregorc4b4e7b2008-12-24 02:52:09 +0000252 TemplateParameterList TemplateParams;
253 SourceLocation LParenLoc, RParenLoc;
254 if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc,
255 RParenLoc)) {
Douglas Gregoradcac882008-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.
269 IdentifierInfo* ident = 0;
270 if(Tok.is(tok::identifier)) {
271 ident = Tok.getIdentifierInfo();
272 ConsumeToken();
273 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
274 // Unnamed template parameter. Don't have to do anything here, just
275 // don't consume this token.
276 } else {
277 Diag(Tok.getLocation(), diag::err_expected_ident);
278 return 0;
279 }
280
281 // Get the a default value, if given.
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000282 OwningExprResult DefaultExpr(Actions);
Douglas Gregoradcac882008-12-01 23:54:00 +0000283 if(Tok.is(tok::equal)) {
284 ConsumeToken();
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000285 DefaultExpr = ParseCXXIdExpression();
286 if(DefaultExpr.isInvalid()) {
Douglas Gregoradcac882008-12-01 23:54:00 +0000287 return 0;
288 }
289 }
290
291 // FIXME: Add an action for template template parameters.
292 return 0;
293}
294
295/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
296/// template parameters (e.g., in "template<int Size> class array;").
Douglas Gregord6fb7ef2008-12-18 19:37:40 +0000297///
Douglas Gregoradcac882008-12-01 23:54:00 +0000298/// template-parameter:
299/// ...
300/// parameter-declaration
301///
302/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
303/// but that didn't work out to well. Instead, this tries to recrate the basic
304/// parsing of parameter declarations, but tries to constrain it for template
305/// parameters.
Douglas Gregor26236e82008-12-02 00:41:28 +0000306/// FIXME: We need to make a ParseParameterDeclaration that works for
307/// non-type template parameters and normal function parameters.
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000308Parser::DeclTy *
309Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregor26236e82008-12-02 00:41:28 +0000310 SourceLocation StartLoc = Tok.getLocation();
Douglas Gregoradcac882008-12-01 23:54:00 +0000311
312 // Parse the declaration-specifiers (i.e., the type).
Douglas Gregor26236e82008-12-02 00:41:28 +0000313 // FIXME: The type should probably be restricted in some way... Not all
Douglas Gregoradcac882008-12-01 23:54:00 +0000314 // declarators (parts of declarators?) are accepted for parameters.
Douglas Gregor26236e82008-12-02 00:41:28 +0000315 DeclSpec DS;
316 ParseDeclarationSpecifiers(DS);
Douglas Gregoradcac882008-12-01 23:54:00 +0000317
318 // Parse this as a typename.
Douglas Gregor26236e82008-12-02 00:41:28 +0000319 Declarator ParamDecl(DS, Declarator::TemplateParamContext);
320 ParseDeclarator(ParamDecl);
Chris Lattner7452c6f2009-01-05 01:24:05 +0000321 if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
Douglas Gregoradcac882008-12-01 23:54:00 +0000322 // This probably shouldn't happen - and it's more of a Sema thing, but
323 // basically we didn't parse the type name because we couldn't associate
324 // it with an AST node. we should just skip to the comma or greater.
325 // TODO: This is currently a placeholder for some kind of Sema Error.
326 Diag(Tok.getLocation(), diag::err_parse_error);
327 SkipUntil(tok::comma, tok::greater, true, true);
328 return 0;
329 }
330
Douglas Gregor26236e82008-12-02 00:41:28 +0000331 // Create the parameter.
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +0000332 DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
333 Depth, Position);
Douglas Gregoradcac882008-12-01 23:54:00 +0000334
335 // Is there a default value? Parsing this can be fairly annoying because
336 // we have to stop on the first non-nested (paren'd) '>' as the closure
337 // for the template parameter list. Or a ','.
Chris Lattner7452c6f2009-01-05 01:24:05 +0000338 if (Tok.is(tok::equal)) {
Douglas Gregoradcac882008-12-01 23:54:00 +0000339 // TODO: Implement default non-type values.
340 SkipUntil(tok::comma, tok::greater, true, true);
341 }
342
Douglas Gregor26236e82008-12-02 00:41:28 +0000343 return Param;
Douglas Gregoradcac882008-12-01 23:54:00 +0000344}
Douglas Gregord6fb7ef2008-12-18 19:37:40 +0000345
346/// AnnotateTemplateIdToken - The current token is an identifier that
347/// refers to the template declaration Template, and is followed by a
348/// '<'. Turn this template-id into a template-id annotation token.
349void Parser::AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS) {
350 assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
351 assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
352 "Parser isn't at the beginning of a template-id");
353
354 // Consume the template-name.
355 SourceLocation TemplateNameLoc = ConsumeToken();
356
357 // Consume the '<'.
358 SourceLocation LAngleLoc = ConsumeToken();
359
360 // Parse the optional template-argument-list.
361 TemplateArgList TemplateArgs;
362 if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
363 // Try to find the closing '>'.
364 SkipUntil(tok::greater, true, true);
365
366 // FIXME: What's our recovery strategy for failed template-argument-lists?
367 return;
368 }
369
370 if (Tok.isNot(tok::greater))
371 return;
372
373 // Determine the location of the '>'. We won't actually consume this
374 // token, because we'll be replacing it with the template-id.
375 SourceLocation RAngleLoc = Tok.getLocation();
376
377 Tok.setKind(tok::annot_template_id);
378 Tok.setAnnotationEndLoc(RAngleLoc);
379 Tok.setLocation(TemplateNameLoc);
380 if (SS && SS->isNotEmpty())
381 Tok.setLocation(SS->getBeginLoc());
382
383 TemplateIdAnnotation *TemplateId
384 = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
385 sizeof(TemplateArgTy*) * TemplateArgs.size());
386 TemplateId->TemplateNameLoc = TemplateNameLoc;
387 TemplateId->Template = Template;
388 TemplateId->LAngleLoc = LAngleLoc;
389 TemplateId->NumArgs = TemplateArgs.size();
390 TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
391 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
392 Args[Arg] = TemplateArgs[Arg];
393 Tok.setAnnotationValue(TemplateId);
394
395 // In case the tokens were cached, have Preprocessor replace them with the
396 // annotation token.
397 PP.AnnotateCachedTokens(Tok);
398}
399
400/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
401///
402/// template-argument: [C++ 14.2]
403/// assignment-expression
404/// type-id
405/// id-expression
406Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
407 // FIXME: Implement this!
408 return TemplateArgError();
409}
410
411/// ParseTemplateArgumentList - Parse a C++ template-argument-list
412/// (C++ [temp.names]). Returns true if there was an error.
413///
414/// template-argument-list: [C++ 14.2]
415/// template-argument
416/// template-argument-list ',' template-argument
417bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
418 while (true) {
419 OwningTemplateArgResult Arg = ParseTemplateArgument();
420 if (Arg.isInvalid()) {
421 SkipUntil(tok::comma, tok::greater, true, true);
422 return true;
423 }
424 else
425 TemplateArgs.push_back(Arg.release());
426
427 // If the next token is a comma, consume it and keep reading
428 // arguments.
429 if (Tok.isNot(tok::comma)) break;
430
431 // Consume the comma.
432 ConsumeToken();
433 }
434
435 return Tok.isNot(tok::greater);
436}
437