ParseTemplate.cpp revision 532e19b4e18585d959065e407c51e625baf26d81
1//===--- 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  // Enter template-parameter scope.
31  ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
32
33  // 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);
86
87  return TemplateDecl;
88}
89
90/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
91/// 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) {
102  // 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  }
107  LAngleLoc = ConsumeToken();
108
109  // Try to parse the template parameter list.
110  if (Tok.is(tok::greater))
111    RAngleLoc = ConsumeToken();
112  else if(ParseTemplateParameterList(Depth, TemplateParams)) {
113    if(!Tok.is(tok::greater)) {
114      Diag(Tok.getLocation(), diag::err_expected_greater);
115      return false;
116    }
117    RAngleLoc = ConsumeToken();
118  }
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
130bool
131Parser::ParseTemplateParameterList(unsigned Depth,
132                                   TemplateParameterList &TemplateParams) {
133  while(1) {
134    if (DeclTy* TmpParam
135          = ParseTemplateParameter(Depth, TemplateParams.size())) {
136      TemplateParams.push_back(TmpParam);
137    } else {
138      // 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
176Parser::DeclTy *
177Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
178  if(Tok.is(tok::kw_class) ||
179     (Tok.is(tok::kw_typename) &&
180         // FIXME: Next token has not been annotated!
181	 NextToken().isNot(tok::annot_qualtypename))) {
182    return ParseTypeParameter(Depth, Position);
183  }
184
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);
192}
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
203Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
204  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();
210
211  // Grab the template parameter name (if given)
212  SourceLocation NameLoc;
213  IdentifierInfo* ParamName = 0;
214  if(Tok.is(tok::identifier)) {
215    ParamName = Tok.getIdentifierInfo();
216    NameLoc = ConsumeToken();
217  } 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
226  DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
227						 KeyLoc, ParamName, NameLoc,
228                                                 Depth, Position);
229
230  // Grab a default type id (if given).
231  if(Tok.is(tok::equal)) {
232    SourceLocation EqualLoc = ConsumeToken();
233    if (TypeTy *DefaultType = ParseTypeName())
234      Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
235  }
236
237  return TypeParam;
238}
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
246Parser::DeclTy *
247Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
248  assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
249
250  // Handle the template <...> part.
251  SourceLocation TemplateLoc = ConsumeToken();
252  TemplateParameterList TemplateParams;
253  SourceLocation LParenLoc, RParenLoc;
254  if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc,
255                              RParenLoc)) {
256    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.
282  OwningExprResult DefaultExpr(Actions);
283  if(Tok.is(tok::equal)) {
284    ConsumeToken();
285    DefaultExpr = ParseCXXIdExpression();
286    if(DefaultExpr.isInvalid()) {
287      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;").
297///
298///       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.
306/// FIXME: We need to make a ParseParameterDeclaration that works for
307/// non-type template parameters and normal function parameters.
308Parser::DeclTy *
309Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
310  SourceLocation StartLoc = Tok.getLocation();
311
312  // Parse the declaration-specifiers (i.e., the type).
313  // FIXME: The type should probably be restricted in some way... Not all
314  // declarators (parts of declarators?) are accepted for parameters.
315  DeclSpec DS;
316  ParseDeclarationSpecifiers(DS);
317
318  // Parse this as a typename.
319  Declarator ParamDecl(DS, Declarator::TemplateParamContext);
320  ParseDeclarator(ParamDecl);
321  if(DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
322    // 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
331  // Create the parameter.
332  DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
333                                                        Depth, Position);
334
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 ','.
338  if(Tok.is(tok::equal)) {
339    // TODO: Implement default non-type values.
340    SkipUntil(tok::comma, tok::greater, true, true);
341  }
342
343  return Param;
344}
345
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
438