blob: 5d0c4b5350a9e6c7e4cebfc6ccbe13b05f7a5aa6 [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
30 // Consume the optional export token, if it exists, followed by the
31 // namespace token.
32 bool isExported = false;
33 if(Tok.is(tok::kw_export)) {
34 SourceLocation ExportLoc = ConsumeToken();
35 if(!Tok.is(tok::kw_template)) {
36 Diag(Tok.getLocation(), diag::err_expected_template);
37 return 0;
38 }
39 isExported = true;
40 }
41 SourceLocation TemplateLoc = ConsumeToken();
42
Douglas Gregor8e7f9572008-12-02 00:41:28 +000043 // Enter template-parameter scope.
Douglas Gregor95d40792008-12-10 06:34:36 +000044 ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
Douglas Gregor8e7f9572008-12-02 00:41:28 +000045
46 // Try to parse the template parameters, and the declaration if
47 // successful.
48 DeclTy *TemplateDecl = 0;
Douglas Gregor2fa10442008-12-18 19:37:40 +000049 if (Tok.is(tok::less) && NextToken().is(tok::greater)) {
50 // This is a template specialization. Just consume the angle
51 // brackets and parse the declaration or function definition that
52 // follows.
53 // FIXME: Record somehow that we're in an explicit specialization.
54 ConsumeToken();
55 ConsumeToken();
56 TemplateParmScope.Exit();
Douglas Gregor8e7f9572008-12-02 00:41:28 +000057 TemplateDecl = ParseDeclarationOrFunctionDefinition();
Douglas Gregor2fa10442008-12-18 19:37:40 +000058 } else {
59 if(ParseTemplateParameters(0))
60 TemplateDecl = ParseDeclarationOrFunctionDefinition();
61 }
Douglas Gregor8e7f9572008-12-02 00:41:28 +000062
Douglas Gregor8e7f9572008-12-02 00:41:28 +000063 return TemplateDecl;
Douglas Gregorb3bec712008-12-01 23:54:00 +000064}
65
66/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
67/// angle brackets.
68bool Parser::ParseTemplateParameters(DeclTy* TmpDecl) {
69 // Get the template parameter list.
70 if(!Tok.is(tok::less)) {
71 Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
72 return false;
73 }
74 ConsumeToken();
75
76 // Try to parse the template parameter list.
77 if(ParseTemplateParameterList(0)) {
78 if(!Tok.is(tok::greater)) {
79 Diag(Tok.getLocation(), diag::err_expected_greater);
80 return false;
81 }
82 ConsumeToken();
83 }
84 return true;
85}
86
87/// ParseTemplateParameterList - Parse a template parameter list. If
88/// the parsing fails badly (i.e., closing bracket was left out), this
89/// will try to put the token stream in a reasonable position (closing
90/// a statement, etc.) and return false.
91///
92/// template-parameter-list: [C++ temp]
93/// template-parameter
94/// template-parameter-list ',' template-parameter
95bool Parser::ParseTemplateParameterList(DeclTy* TmpDecl) {
96 // FIXME: For now, this is just going to consume the template parameters.
97 // Eventually, we should pass the template decl AST node as a parameter and
98 // apply template parameters as we find them.
99 while(1) {
100 DeclTy* TmpParam = ParseTemplateParameter();
101 if(!TmpParam) {
102 // If we failed to parse a template parameter, skip until we find
103 // a comma or closing brace.
104 SkipUntil(tok::comma, tok::greater, true, true);
105 }
106
107 // Did we find a comma or the end of the template parmeter list?
108 if(Tok.is(tok::comma)) {
109 ConsumeToken();
110 } else if(Tok.is(tok::greater)) {
111 // Don't consume this... that's done by template parser.
112 break;
113 } else {
114 // Somebody probably forgot to close the template. Skip ahead and
115 // try to get out of the expression. This error is currently
116 // subsumed by whatever goes on in ParseTemplateParameter.
117 // TODO: This could match >>, and it would be nice to avoid those
118 // silly errors with template <vec<T>>.
119 // Diag(Tok.getLocation(), diag::err_expected_comma_greater);
120 SkipUntil(tok::greater, true, true);
121 return false;
122 }
123 }
124 return true;
125}
126
127/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
128///
129/// template-parameter: [C++ temp.param]
130/// type-parameter
131/// parameter-declaration
132///
133/// type-parameter: (see below)
134/// 'class' identifier[opt]
135/// 'class' identifier[opt] '=' type-id
136/// 'typename' identifier[opt]
137/// 'typename' identifier[opt] '=' type-id
138/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
139/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
140Parser::DeclTy *Parser::ParseTemplateParameter() {
141 TryAnnotateCXXScopeToken();
142
143 if(Tok.is(tok::kw_class)
144 || (Tok.is(tok::kw_typename) &&
145 NextToken().isNot(tok::annot_qualtypename))) {
146 return ParseTypeParameter();
147 } else if(Tok.is(tok::kw_template)) {
148 return ParseTemplateTemplateParameter();
149 } else {
150 // If it's none of the above, then it must be a parameter declaration.
151 // NOTE: This will pick up errors in the closure of the template parameter
152 // list (e.g., template < ; Check here to implement >> style closures.
153 return ParseNonTypeTemplateParameter();
154 }
155 return 0;
156}
157
158/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
159/// Other kinds of template parameters are parsed in
160/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
161///
162/// type-parameter: [C++ temp.param]
163/// 'class' identifier[opt]
164/// 'class' identifier[opt] '=' type-id
165/// 'typename' identifier[opt]
166/// 'typename' identifier[opt] '=' type-id
167Parser::DeclTy *Parser::ParseTypeParameter() {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000168 assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
169 "A type-parameter starts with 'class' or 'typename'");
170
171 // Consume the 'class' or 'typename' keyword.
172 bool TypenameKeyword = Tok.is(tok::kw_typename);
173 SourceLocation KeyLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000174
175 // Grab the template parameter name (if given)
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000176 SourceLocation NameLoc;
177 IdentifierInfo* ParamName = 0;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000178 if(Tok.is(tok::identifier)) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000179 ParamName = Tok.getIdentifierInfo();
180 NameLoc = ConsumeToken();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000181 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) ||
182 Tok.is(tok::greater)) {
183 // Unnamed template parameter. Don't have to do anything here, just
184 // don't consume this token.
185 } else {
186 Diag(Tok.getLocation(), diag::err_expected_ident);
187 return 0;
188 }
189
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000190 DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
191 KeyLoc, ParamName, NameLoc);
192
Douglas Gregorb3bec712008-12-01 23:54:00 +0000193 // Grab a default type id (if given).
Douglas Gregorb3bec712008-12-01 23:54:00 +0000194 if(Tok.is(tok::equal)) {
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000195 SourceLocation EqualLoc = ConsumeToken();
196 TypeTy *DefaultType = ParseTypeName();
197 if(DefaultType)
198 Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000199 }
200
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000201 return TypeParam;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000202}
203
204/// ParseTemplateTemplateParameter - Handle the parsing of template
205/// template parameters.
206///
207/// type-parameter: [C++ temp.param]
208/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
209/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
210Parser::DeclTy* Parser::ParseTemplateTemplateParameter() {
211 assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
212
213 // Handle the template <...> part.
214 SourceLocation TemplateLoc = ConsumeToken();
215 if(!ParseTemplateParameters(0)) {
216 return 0;
217 }
218
219 // Generate a meaningful error if the user forgot to put class before the
220 // identifier, comma, or greater.
221 if(!Tok.is(tok::kw_class)) {
222 Diag(Tok.getLocation(), diag::err_expected_class_before)
223 << PP.getSpelling(Tok);
224 return 0;
225 }
226 SourceLocation ClassLoc = ConsumeToken();
227
228 // Get the identifier, if given.
229 IdentifierInfo* ident = 0;
230 if(Tok.is(tok::identifier)) {
231 ident = Tok.getIdentifierInfo();
232 ConsumeToken();
233 } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
234 // Unnamed template parameter. Don't have to do anything here, just
235 // don't consume this token.
236 } else {
237 Diag(Tok.getLocation(), diag::err_expected_ident);
238 return 0;
239 }
240
241 // Get the a default value, if given.
Sebastian Redl62261042008-12-09 20:22:58 +0000242 OwningExprResult DefaultExpr(Actions);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000243 if(Tok.is(tok::equal)) {
244 ConsumeToken();
Sebastian Redlbb4dae72008-12-09 13:15:23 +0000245 DefaultExpr = ParseCXXIdExpression();
246 if(DefaultExpr.isInvalid()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000247 return 0;
248 }
249 }
250
251 // FIXME: Add an action for template template parameters.
252 return 0;
253}
254
255/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
256/// template parameters (e.g., in "template<int Size> class array;").
Douglas Gregor2fa10442008-12-18 19:37:40 +0000257///
Douglas Gregorb3bec712008-12-01 23:54:00 +0000258/// template-parameter:
259/// ...
260/// parameter-declaration
261///
262/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
263/// but that didn't work out to well. Instead, this tries to recrate the basic
264/// parsing of parameter declarations, but tries to constrain it for template
265/// parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000266/// FIXME: We need to make a ParseParameterDeclaration that works for
267/// non-type template parameters and normal function parameters.
268Parser::DeclTy* Parser::ParseNonTypeTemplateParameter() {
269 SourceLocation StartLoc = Tok.getLocation();
Douglas Gregorb3bec712008-12-01 23:54:00 +0000270
271 // Parse the declaration-specifiers (i.e., the type).
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000272 // FIXME: The type should probably be restricted in some way... Not all
Douglas Gregorb3bec712008-12-01 23:54:00 +0000273 // declarators (parts of declarators?) are accepted for parameters.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000274 DeclSpec DS;
275 ParseDeclarationSpecifiers(DS);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000276
277 // Parse this as a typename.
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000278 Declarator ParamDecl(DS, Declarator::TemplateParamContext);
279 ParseDeclarator(ParamDecl);
280 if(DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
Douglas Gregorb3bec712008-12-01 23:54:00 +0000281 // This probably shouldn't happen - and it's more of a Sema thing, but
282 // basically we didn't parse the type name because we couldn't associate
283 // it with an AST node. we should just skip to the comma or greater.
284 // TODO: This is currently a placeholder for some kind of Sema Error.
285 Diag(Tok.getLocation(), diag::err_parse_error);
286 SkipUntil(tok::comma, tok::greater, true, true);
287 return 0;
288 }
289
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000290 // Create the parameter.
291 DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl);
Douglas Gregorb3bec712008-12-01 23:54:00 +0000292
293 // Is there a default value? Parsing this can be fairly annoying because
294 // we have to stop on the first non-nested (paren'd) '>' as the closure
295 // for the template parameter list. Or a ','.
296 if(Tok.is(tok::equal)) {
297 // TODO: Implement default non-type values.
298 SkipUntil(tok::comma, tok::greater, true, true);
299 }
300
Douglas Gregor8e7f9572008-12-02 00:41:28 +0000301 return Param;
Douglas Gregorb3bec712008-12-01 23:54:00 +0000302}
Douglas Gregor2fa10442008-12-18 19:37:40 +0000303
304/// AnnotateTemplateIdToken - The current token is an identifier that
305/// refers to the template declaration Template, and is followed by a
306/// '<'. Turn this template-id into a template-id annotation token.
307void Parser::AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS) {
308 assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
309 assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
310 "Parser isn't at the beginning of a template-id");
311
312 // Consume the template-name.
313 SourceLocation TemplateNameLoc = ConsumeToken();
314
315 // Consume the '<'.
316 SourceLocation LAngleLoc = ConsumeToken();
317
318 // Parse the optional template-argument-list.
319 TemplateArgList TemplateArgs;
320 if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
321 // Try to find the closing '>'.
322 SkipUntil(tok::greater, true, true);
323
324 // FIXME: What's our recovery strategy for failed template-argument-lists?
325 return;
326 }
327
328 if (Tok.isNot(tok::greater))
329 return;
330
331 // Determine the location of the '>'. We won't actually consume this
332 // token, because we'll be replacing it with the template-id.
333 SourceLocation RAngleLoc = Tok.getLocation();
334
335 Tok.setKind(tok::annot_template_id);
336 Tok.setAnnotationEndLoc(RAngleLoc);
337 Tok.setLocation(TemplateNameLoc);
338 if (SS && SS->isNotEmpty())
339 Tok.setLocation(SS->getBeginLoc());
340
341 TemplateIdAnnotation *TemplateId
342 = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
343 sizeof(TemplateArgTy*) * TemplateArgs.size());
344 TemplateId->TemplateNameLoc = TemplateNameLoc;
345 TemplateId->Template = Template;
346 TemplateId->LAngleLoc = LAngleLoc;
347 TemplateId->NumArgs = TemplateArgs.size();
348 TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
349 for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
350 Args[Arg] = TemplateArgs[Arg];
351 Tok.setAnnotationValue(TemplateId);
352
353 // In case the tokens were cached, have Preprocessor replace them with the
354 // annotation token.
355 PP.AnnotateCachedTokens(Tok);
356}
357
358/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
359///
360/// template-argument: [C++ 14.2]
361/// assignment-expression
362/// type-id
363/// id-expression
364Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
365 // FIXME: Implement this!
366 return TemplateArgError();
367}
368
369/// ParseTemplateArgumentList - Parse a C++ template-argument-list
370/// (C++ [temp.names]). Returns true if there was an error.
371///
372/// template-argument-list: [C++ 14.2]
373/// template-argument
374/// template-argument-list ',' template-argument
375bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
376 while (true) {
377 OwningTemplateArgResult Arg = ParseTemplateArgument();
378 if (Arg.isInvalid()) {
379 SkipUntil(tok::comma, tok::greater, true, true);
380 return true;
381 }
382 else
383 TemplateArgs.push_back(Arg.release());
384
385 // If the next token is a comma, consume it and keep reading
386 // arguments.
387 if (Tok.isNot(tok::comma)) break;
388
389 // Consume the comma.
390 ConsumeToken();
391 }
392
393 return Tok.isNot(tok::greater);
394}
395