blob: bd937d447a00db074921f63d15c4a35abaf093b3 [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"
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 Gregor8e7f9572008-12-02 00:41:28 +000030 // Enter template-parameter scope.
Douglas Gregor95d40792008-12-10 06:34:36 +000031 ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
Douglas Gregor8e7f9572008-12-02 00:41:28 +000032
Douglas Gregor52473432008-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 Gregor8e7f9572008-12-02 00:41:28 +000086
Douglas Gregor8e7f9572008-12-02 00:41:28 +000087 return TemplateDecl;
Douglas Gregorb3bec712008-12-01 23:54:00 +000088}
89
90/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
Douglas Gregor52473432008-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 Gregorb3bec712008-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 Gregor52473432008-12-24 02:52:09 +0000107 LAngleLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000108
109 // Try to parse the template parameter list.
Douglas Gregor52473432008-12-24 02:52:09 +0000110 if (Tok.is(tok::greater))
111 RAngleLoc = ConsumeToken();
112 else if(ParseTemplateParameterList(Depth, TemplateParams)) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000113 if(!Tok.is(tok::greater)) {
114 Diag(Tok.getLocation(), diag::err_expected_greater);
115 return false;
116 }
Douglas Gregor52473432008-12-24 02:52:09 +0000117 RAngleLoc = ConsumeToken();
Douglas Gregorb3bec712008-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 Gregor52473432008-12-24 02:52:09 +0000130bool
131Parser::ParseTemplateParameterList(unsigned Depth,
132 TemplateParameterList &TemplateParams) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000133 while(1) {
Douglas Gregor52473432008-12-24 02:52:09 +0000134 if (DeclTy* TmpParam
135 = ParseTemplateParameter(Depth, TemplateParams.size())) {
136 TemplateParams.push_back(TmpParam);
137 } else {
Douglas Gregorb3bec712008-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 Gregor52473432008-12-24 02:52:09 +0000176Parser::DeclTy *
177Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000178 TryAnnotateCXXScopeToken();
179
180 if(Tok.is(tok::kw_class)
181 || (Tok.is(tok::kw_typename) &&
182 NextToken().isNot(tok::annot_qualtypename))) {
Douglas Gregor52473432008-12-24 02:52:09 +0000183 return ParseTypeParameter(Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000184 } else if(Tok.is(tok::kw_template)) {
Douglas Gregor52473432008-12-24 02:52:09 +0000185 return ParseTemplateTemplateParameter(Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000186 } else {
187 // If it's none of the above, then it must be a parameter declaration.
188 // NOTE: This will pick up errors in the closure of the template parameter
189 // list (e.g., template < ; Check here to implement >> style closures.
Douglas Gregor52473432008-12-24 02:52:09 +0000190 return ParseNonTypeTemplateParameter(Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000191 }
192 return 0;
193}
194
195/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
196/// Other kinds of template parameters are parsed in
197/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
198///
199/// type-parameter: [C++ temp.param]
200/// 'class' identifier[opt]
201/// 'class' identifier[opt] '=' type-id
202/// 'typename' identifier[opt]
203/// 'typename' identifier[opt] '=' type-id
Douglas Gregor52473432008-12-24 02:52:09 +0000204Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000205 assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
206 "A type-parameter starts with 'class' or 'typename'");
207
208 // Consume the 'class' or 'typename' keyword.
209 bool TypenameKeyword = Tok.is(tok::kw_typename);
210 SourceLocation KeyLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000211
212 // Grab the template parameter name (if given)
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000213 SourceLocation NameLoc;
214 IdentifierInfo* ParamName = 0;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000215 if(Tok.is(tok::identifier)) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000216 ParamName = Tok.getIdentifierInfo();
217 NameLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000218 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) ||
219 Tok.is(tok::greater)) {
220 // Unnamed template parameter. Don't have to do anything here, just
221 // don't consume this token.
222 } else {
223 Diag(Tok.getLocation(), diag::err_expected_ident);
224 return 0;
225 }
226
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000227 DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
Douglas Gregor52473432008-12-24 02:52:09 +0000228 KeyLoc, ParamName, NameLoc,
229 Depth, Position);
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000230
Douglas Gregorb3bec712008-12-01 23:54:00 +0000231 // Grab a default type id (if given).
Douglas Gregorb3bec712008-12-01 23:54:00 +0000232 if(Tok.is(tok::equal)) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000233 SourceLocation EqualLoc = ConsumeToken();
Douglas Gregor52473432008-12-24 02:52:09 +0000234 if (TypeTy *DefaultType = ParseTypeName())
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000235 Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000236 }
237
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000238 return TypeParam;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000239}
240
241/// ParseTemplateTemplateParameter - Handle the parsing of template
242/// template parameters.
243///
244/// type-parameter: [C++ temp.param]
245/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
246/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Douglas Gregor52473432008-12-24 02:52:09 +0000247Parser::DeclTy *
248Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000249 assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
250
251 // Handle the template <...> part.
252 SourceLocation TemplateLoc = ConsumeToken();
Douglas Gregor52473432008-12-24 02:52:09 +0000253 TemplateParameterList TemplateParams;
254 SourceLocation LParenLoc, RParenLoc;
255 if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc,
256 RParenLoc)) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000257 return 0;
258 }
259
260 // Generate a meaningful error if the user forgot to put class before the
261 // identifier, comma, or greater.
262 if(!Tok.is(tok::kw_class)) {
263 Diag(Tok.getLocation(), diag::err_expected_class_before)
264 << PP.getSpelling(Tok);
265 return 0;
266 }
267 SourceLocation ClassLoc = ConsumeToken();
268
269 // Get the identifier, if given.
270 IdentifierInfo* ident = 0;
271 if(Tok.is(tok::identifier)) {
272 ident = Tok.getIdentifierInfo();
273 ConsumeToken();
274 } 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
282 // Get the a default value, if given.
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
292 // FIXME: Add an action for template template parameters.
293 return 0;
294}
295
296/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
297/// template parameters (e.g., in "template<int Size> class array;").
Douglas Gregor2fa10442008-12-18 19:37:40 +0000298///
Douglas Gregorb3bec712008-12-01 23:54:00 +0000299/// template-parameter:
300/// ...
301/// parameter-declaration
302///
303/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
304/// but that didn't work out to well. Instead, this tries to recrate the basic
305/// parsing of parameter declarations, but tries to constrain it for template
306/// parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000307/// FIXME: We need to make a ParseParameterDeclaration that works for
308/// non-type template parameters and normal function parameters.
Douglas Gregor52473432008-12-24 02:52:09 +0000309Parser::DeclTy *
310Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000311 SourceLocation StartLoc = Tok.getLocation();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000312
313 // Parse the declaration-specifiers (i.e., the type).
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000314 // FIXME: The type should probably be restricted in some way... Not all
Douglas Gregorb3bec712008-12-01 23:54:00 +0000315 // declarators (parts of declarators?) are accepted for parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000316 DeclSpec DS;
317 ParseDeclarationSpecifiers(DS);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000318
319 // Parse this as a typename.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000320 Declarator ParamDecl(DS, Declarator::TemplateParamContext);
321 ParseDeclarator(ParamDecl);
322 if(DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000323 // This probably shouldn't happen - and it's more of a Sema thing, but
324 // basically we didn't parse the type name because we couldn't associate
325 // it with an AST node. we should just skip to the comma or greater.
326 // TODO: This is currently a placeholder for some kind of Sema Error.
327 Diag(Tok.getLocation(), diag::err_parse_error);
328 SkipUntil(tok::comma, tok::greater, true, true);
329 return 0;
330 }
331
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000332 // Create the parameter.
Douglas Gregor52473432008-12-24 02:52:09 +0000333 DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
334 Depth, Position);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000335
336 // Is there a default value? Parsing this can be fairly annoying because
337 // we have to stop on the first non-nested (paren'd) '>' as the closure
338 // for the template parameter list. Or a ','.
339 if(Tok.is(tok::equal)) {
340 // TODO: Implement default non-type values.
341 SkipUntil(tok::comma, tok::greater, true, true);
342 }
343
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000344 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000345}
Douglas Gregor2fa10442008-12-18 19:37:40 +0000346
347/// AnnotateTemplateIdToken - The current token is an identifier that
348/// refers to the template declaration Template, and is followed by a
349/// '<'. Turn this template-id into a template-id annotation token.
350void Parser::AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS) {
351 assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
352 assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
353 "Parser isn't at the beginning of a template-id");
354
355 // Consume the template-name.
356 SourceLocation TemplateNameLoc = ConsumeToken();
357
358 // Consume the '<'.
359 SourceLocation LAngleLoc = ConsumeToken();
360
361 // Parse the optional template-argument-list.
362 TemplateArgList TemplateArgs;
363 if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
364 // Try to find the closing '>'.
365 SkipUntil(tok::greater, true, true);
366
367 // FIXME: What's our recovery strategy for failed template-argument-lists?
368 return;
369 }
370
371 if (Tok.isNot(tok::greater))
372 return;
373
374 // Determine the location of the '>'. We won't actually consume this
375 // token, because we'll be replacing it with the template-id.
376 SourceLocation RAngleLoc = Tok.getLocation();
377
378 Tok.setKind(tok::annot_template_id);
379 Tok.setAnnotationEndLoc(RAngleLoc);
380 Tok.setLocation(TemplateNameLoc);
381 if (SS && SS->isNotEmpty())
382 Tok.setLocation(SS->getBeginLoc());
383
384 TemplateIdAnnotation *TemplateId
385 = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
386 sizeof(TemplateArgTy*) * TemplateArgs.size());
387 TemplateId->TemplateNameLoc = TemplateNameLoc;
388 TemplateId->Template = Template;
389 TemplateId->LAngleLoc = LAngleLoc;
390 TemplateId->NumArgs = TemplateArgs.size();
391 TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
392 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
393 Args[Arg] = TemplateArgs[Arg];
394 Tok.setAnnotationValue(TemplateId);
395
396 // In case the tokens were cached, have Preprocessor replace them with the
397 // annotation token.
398 PP.AnnotateCachedTokens(Tok);
399}
400
401/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
402///
403/// template-argument: [C++ 14.2]
404/// assignment-expression
405/// type-id
406/// id-expression
407Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
408 // FIXME: Implement this!
409 return TemplateArgError();
410}
411
412/// ParseTemplateArgumentList - Parse a C++ template-argument-list
413/// (C++ [temp.names]). Returns true if there was an error.
414///
415/// template-argument-list: [C++ 14.2]
416/// template-argument
417/// template-argument-list ',' template-argument
418bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
419 while (true) {
420 OwningTemplateArgResult Arg = ParseTemplateArgument();
421 if (Arg.isInvalid()) {
422 SkipUntil(tok::comma, tok::greater, true, true);
423 return true;
424 }
425 else
426 TemplateArgs.push_back(Arg.release());
427
428 // If the next token is a comma, consume it and keep reading
429 // arguments.
430 if (Tok.isNot(tok::comma)) break;
431
432 // Consume the comma.
433 ConsumeToken();
434 }
435
436 return Tok.isNot(tok::greater);
437}
438