 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
81.8% |
224 / 274 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
94.9% |
260 / 274 |
| |
|
Line Coverage: |
92.7% |
332 / 358 |
| |
 |
|
 |
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/Parse/ParseDiagnostic.h"
16 : #include "clang/Parse/DeclSpec.h"
17 : #include "clang/Parse/Scope.h"
18 : #include "clang/Parse/Template.h"
19 : #include "RAIIObjectsForParser.h"
20 : using namespace clang;
21 :
22 : /// \brief Parse a template declaration, explicit instantiation, or
23 : /// explicit specialization.
24 : Parser::DeclPtrTy
25 : Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
26 : SourceLocation &DeclEnd,
27 2191: AccessSpecifier AS) {
2188: branch 1 taken
3: branch 2 taken
359: branch 5 taken
1829: branch 6 taken
359: branch 7 taken
1832: branch 8 taken
28 2191: if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less))
29 : return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
30 359: DeclEnd);
31 :
32 1832: return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
33 : }
34 :
35 : /// \brief RAII class that manages the template parameter depth.
36 : namespace {
37 : class TemplateParameterDepthCounter {
38 : unsigned &Depth;
39 : unsigned AddedLevels;
40 :
41 : public:
42 1832: explicit TemplateParameterDepthCounter(unsigned &Depth)
43 1832: : Depth(Depth), AddedLevels(0) { }
44 :
45 1832: ~TemplateParameterDepthCounter() {
46 1832: Depth -= AddedLevels;
47 1832: }
48 :
49 1648: void operator++() {
50 1648: ++Depth;
51 1648: ++AddedLevels;
52 1648: }
53 :
54 3777: operator unsigned() const { return Depth; }
55 : };
56 : }
57 :
58 : /// \brief Parse a template declaration or an explicit specialization.
59 : ///
60 : /// Template declarations include one or more template parameter lists
61 : /// and either the function or class template declaration. Explicit
62 : /// specializations contain one or more 'template < >' prefixes
63 : /// followed by a (possibly templated) declaration. Since the
64 : /// syntactic form of both features is nearly identical, we parse all
65 : /// of the template headers together and let semantic analysis sort
66 : /// the declarations from the explicit specializations.
67 : ///
68 : /// template-declaration: [C++ temp]
69 : /// 'export'[opt] 'template' '<' template-parameter-list '>' declaration
70 : ///
71 : /// explicit-specialization: [ C++ temp.expl.spec]
72 : /// 'template' '<' '>' declaration
73 : Parser::DeclPtrTy
74 : Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
75 : SourceLocation &DeclEnd,
76 1832: AccessSpecifier AS) {
77 : assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
1829: branch 1 taken
3: branch 2 taken
1829: branch 4 taken
0: branch 5 not taken
78 1832: "Token does not start a template declaration.");
79 :
80 : // Enter template-parameter scope.
81 1832: ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
82 :
83 : // Parse multiple levels of template headers within this template
84 : // parameter scope, e.g.,
85 : //
86 : // template<typename T>
87 : // template<typename U>
88 : // class A<T>::B { ... };
89 : //
90 : // We parse multiple levels non-recursively so that we can build a
91 : // single data structure containing all of the template parameter
92 : // lists to easily differentiate between the case above and:
93 : //
94 : // template<typename T>
95 : // class A {
96 : // template<typename U> class B;
97 : // };
98 : //
99 : // In the first case, the action for declaring A<T>::B receives
100 : // both template parameter lists. In the second case, the action for
101 : // defining A<T>::B receives just the inner template parameter list
102 : // (and retrieves the outer template parameter list from its
103 : // context).
104 1832: bool isSpecialization = true;
105 1832: bool LastParamListWasEmpty = false;
106 1832: TemplateParameterLists ParamLists;
107 1832: TemplateParameterDepthCounter Depth(TemplateParameterDepth);
1888: branch 1 taken
0: branch 2 not taken
58: branch 4 taken
1830: branch 5 taken
58: branch 6 taken
1830: branch 7 taken
108 1888: do {
109 : // Consume the 'export', if any.
110 1890: SourceLocation ExportLoc;
3: branch 1 taken
1887: branch 2 taken
111 1890: if (Tok.is(tok::kw_export)) {
112 3: ExportLoc = ConsumeToken();
113 : }
114 :
115 : // Consume the 'template', which should be here.
116 1890: SourceLocation TemplateLoc;
1889: branch 1 taken
1: branch 2 taken
117 1890: if (Tok.is(tok::kw_template)) {
118 1889: TemplateLoc = ConsumeToken();
119 : } else {
120 1: Diag(Tok.getLocation(), diag::err_expected_template);
121 1: return DeclPtrTy();
122 : }
123 :
124 : // Parse the '<' template-parameter-list '>'
125 1889: SourceLocation LAngleLoc, RAngleLoc;
126 1889: TemplateParameterList TemplateParams;
1: branch 2 taken
1888: branch 3 taken
127 1889: if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
128 : RAngleLoc)) {
129 : // Skip until the semi-colon or a }.
130 1: SkipUntil(tok::r_brace, true, true);
1: branch 1 taken
0: branch 2 not taken
131 1: if (Tok.is(tok::semi))
132 1: ConsumeToken();
133 1: return DeclPtrTy();
134 : }
135 :
136 : ParamLists.push_back(
137 : Actions.ActOnTemplateParameterList(Depth, ExportLoc,
138 : TemplateLoc, LAngleLoc,
139 : TemplateParams.data(),
140 1888: TemplateParams.size(), RAngleLoc));
141 :
1648: branch 1 taken
240: branch 2 taken
142 1888: if (!TemplateParams.empty()) {
143 1648: isSpecialization = false;
144 1648: ++Depth;
145 : } else {
146 240: LastParamListWasEmpty = true;
1888: branch 1 taken
1: branch 2 taken
147 1889: }
148 : } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
149 :
150 : // Parse the actual template declaration.
151 : return ParseSingleDeclarationAfterTemplate(Context,
152 : ParsedTemplateInfo(&ParamLists,
153 : isSpecialization,
154 : LastParamListWasEmpty),
155 1830: DeclEnd, AS);
156 : }
157 :
158 : /// \brief Parse a single declaration that declares a template,
159 : /// template specialization, or explicit instantiation of a template.
160 : ///
161 : /// \param TemplateParams if non-NULL, the template parameter lists
162 : /// that preceded this declaration. In this case, the declaration is a
163 : /// template declaration, out-of-line definition of a template, or an
164 : /// explicit template specialization. When NULL, the declaration is an
165 : /// explicit template instantiation.
166 : ///
167 : /// \param TemplateLoc when TemplateParams is NULL, the location of
168 : /// the 'template' keyword that indicates that we have an explicit
169 : /// template instantiation.
170 : ///
171 : /// \param DeclEnd will receive the source location of the last token
172 : /// within this declaration.
173 : ///
174 : /// \param AS the access specifier associated with this
175 : /// declaration. Will be AS_none for namespace-scope declarations.
176 : ///
177 : /// \returns the new declaration.
178 : Parser::DeclPtrTy
179 : Parser::ParseSingleDeclarationAfterTemplate(
180 : unsigned Context,
181 : const ParsedTemplateInfo &TemplateInfo,
182 : SourceLocation &DeclEnd,
183 2207: AccessSpecifier AS) {
184 : assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
0: branch 0 not taken
2207: branch 1 taken
185 2207: "Template information required");
186 :
201: branch 0 taken
2006: branch 1 taken
187 2207: if (Context == Declarator::MemberContext) {
188 : // We are parsing a member template.
189 201: ParseCXXClassMemberDeclaration(AS, TemplateInfo);
190 201: return DeclPtrTy::make((void*)0);
191 : }
192 :
193 : // Parse the declaration specifiers.
194 2006: ParsingDeclSpec DS(*this);
195 :
96: branch 1 taken
1910: branch 2 taken
1: branch 4 taken
95: branch 5 taken
1: branch 6 taken
2005: branch 7 taken
196 2006: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
197 1: DS.AddAttributes(ParseCXX0XAttributes().AttrList);
198 :
199 : ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
200 2006: getDeclSpecContextFromDeclaratorContext(Context));
201 :
1358: branch 1 taken
648: branch 2 taken
202 2006: if (Tok.is(tok::semi)) {
203 1358: DeclEnd = ConsumeToken();
204 1358: DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
205 1358: DS.complete(Decl);
206 1358: return Decl;
207 : }
208 :
209 : // Parse the declarator.
210 648: ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
211 648: ParseDeclarator(DeclaratorInfo);
212 : // Error parsing the declarator?
1: branch 1 taken
647: branch 2 taken
213 648: if (!DeclaratorInfo.hasName()) {
214 : // If so, skip until the semi-colon or a }.
215 1: SkipUntil(tok::r_brace, true, true);
1: branch 1 taken
0: branch 2 not taken
216 1: if (Tok.is(tok::semi))
217 1: ConsumeToken();
218 1: return DeclPtrTy();
219 : }
220 :
221 : // If we have a declaration or declarator list, handle it.
348: branch 1 taken
299: branch 2 taken
222 647: if (isDeclarationAfterDeclarator()) {
223 : // Parse this declaration.
224 : DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
225 348: TemplateInfo);
226 :
1: branch 1 taken
347: branch 2 taken
227 348: if (Tok.is(tok::comma)) {
228 : Diag(Tok, diag::err_multiple_template_declarators)
229 1: << (int)TemplateInfo.Kind;
230 1: SkipUntil(tok::semi, true, false);
231 1: return ThisDecl;
232 : }
233 :
234 : // Eat the semi colon after the declaration.
235 347: ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
236 347: DS.complete(ThisDecl);
237 347: return ThisDecl;
238 : }
239 :
297: branch 1 taken
2: branch 2 taken
297: branch 4 taken
0: branch 5 not taken
297: branch 6 taken
2: branch 7 taken
240 299: if (DeclaratorInfo.isFunctionDeclarator() &&
241 : isStartOfFunctionDefinition()) {
0: branch 1 not taken
297: branch 2 taken
242 297: if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
243 0: Diag(Tok, diag::err_function_declared_typedef);
244 :
0: branch 1 not taken
0: branch 2 not taken
245 0: if (Tok.is(tok::l_brace)) {
246 : // This recovery skips the entire function body. It would be nice
247 : // to simply call ParseFunctionDefinition() below, however Sema
248 : // assumes the declarator represents a function, not a typedef.
249 0: ConsumeBrace();
250 0: SkipUntil(tok::r_brace, true);
251 : } else {
252 0: SkipUntil(tok::semi);
253 : }
254 0: return DeclPtrTy();
255 : }
256 297: return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo);
257 : }
258 :
0: branch 1 not taken
2: branch 2 taken
259 2: if (DeclaratorInfo.isFunctionDeclarator())
260 0: Diag(Tok, diag::err_expected_fn_body);
261 : else
262 2: Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
263 2: SkipUntil(tok::semi);
264 2: return DeclPtrTy();
265 : }
266 :
267 : /// ParseTemplateParameters - Parses a template-parameter-list enclosed in
268 : /// angle brackets. Depth is the depth of this template-parameter-list, which
269 : /// is the number of template headers directly enclosing this template header.
270 : /// TemplateParams is the current list of template parameters we're building.
271 : /// The template parameter we parse will be added to this list. LAngleLoc and
272 : /// RAngleLoc will receive the positions of the '<' and '>', respectively,
273 : /// that enclose this template parameter list.
274 : ///
275 : /// \returns true if an error occurred, false otherwise.
276 : bool Parser::ParseTemplateParameters(unsigned Depth,
277 : TemplateParameterList &TemplateParams,
278 : SourceLocation &LAngleLoc,
279 1948: SourceLocation &RAngleLoc) {
280 : // Get the template parameter list.
2: branch 1 taken
1946: branch 2 taken
281 1948: if (!Tok.is(tok::less)) {
282 2: Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
283 2: return true;
284 : }
285 1946: LAngleLoc = ConsumeToken();
286 :
287 : // Try to parse the template parameter list.
236: branch 1 taken
1710: branch 2 taken
288 1946: if (Tok.is(tok::greater))
289 236: RAngleLoc = ConsumeToken();
1709: branch 1 taken
1: branch 2 taken
290 1710: else if (ParseTemplateParameterList(Depth, TemplateParams)) {
0: branch 1 not taken
1709: branch 2 taken
291 1709: if (!Tok.is(tok::greater)) {
292 0: Diag(Tok.getLocation(), diag::err_expected_greater);
293 0: return true;
294 : }
295 1709: RAngleLoc = ConsumeToken();
296 : }
297 1946: return false;
298 : }
299 :
300 : /// ParseTemplateParameterList - Parse a template parameter list. If
301 : /// the parsing fails badly (i.e., closing bracket was left out), this
302 : /// will try to put the token stream in a reasonable position (closing
303 : /// a statement, etc.) and return false.
304 : ///
305 : /// template-parameter-list: [C++ temp]
306 : /// template-parameter
307 : /// template-parameter-list ',' template-parameter
308 : bool
309 : Parser::ParseTemplateParameterList(unsigned Depth,
310 2165: TemplateParameterList &TemplateParams) {
311 455: while (1) {
2161: branch 1 taken
4: branch 2 taken
312 2165: if (DeclPtrTy TmpParam
313 2165: = ParseTemplateParameter(Depth, TemplateParams.size())) {
314 2161: TemplateParams.push_back(TmpParam);
315 : } else {
316 : // If we failed to parse a template parameter, skip until we find
317 : // a comma or closing brace.
318 4: SkipUntil(tok::comma, tok::greater, true, true);
319 : }
320 :
321 : // Did we find a comma or the end of the template parmeter list?
455: branch 1 taken
1710: branch 2 taken
322 2165: if (Tok.is(tok::comma)) {
323 455: ConsumeToken();
1: branch 1 taken
1709: branch 2 taken
324 1710: } else if (Tok.is(tok::greater)) {
325 : // Don't consume this... that's done by template parser.
326 1709: break;
327 : } else {
328 : // Somebody probably forgot to close the template. Skip ahead and
329 : // try to get out of the expression. This error is currently
330 : // subsumed by whatever goes on in ParseTemplateParameter.
331 : // TODO: This could match >>, and it would be nice to avoid those
332 : // silly errors with template <vec<T>>.
333 : // Diag(Tok.getLocation(), diag::err_expected_comma_greater);
334 1: SkipUntil(tok::greater, true, true);
335 1: return false;
336 : }
337 : }
338 1709: return true;
339 : }
340 :
341 : /// \brief Determine whether the parser is at the start of a template
342 : /// type parameter.
343 2165: bool Parser::isStartOfTemplateTypeParameter() {
322: branch 1 taken
1843: branch 2 taken
344 2165: if (Tok.is(tok::kw_class))
345 322: return true;
346 :
450: branch 1 taken
1393: branch 2 taken
347 1843: if (Tok.isNot(tok::kw_typename))
348 450: return false;
349 :
350 : // C++ [temp.param]p2:
351 : // There is no semantic difference between class and typename in a
352 : // template-parameter. typename followed by an unqualified-id
353 : // names a template type parameter. typename followed by a
354 : // qualified-id denotes the type in a non-type
355 : // parameter-declaration.
356 1393: Token Next = NextToken();
357 :
358 : // If we have an identifier, skip over it.
1323: branch 1 taken
70: branch 2 taken
359 1393: if (Next.getKind() == tok::identifier)
360 1323: Next = GetLookAheadToken(2);
361 :
1391: branch 1 taken
2: branch 2 taken
362 1393: switch (Next.getKind()) {
363 : case tok::equal:
364 : case tok::comma:
365 : case tok::greater:
366 : case tok::greatergreater:
367 : case tok::ellipsis:
368 1391: return true;
369 :
370 : default:
371 2: return false;
372 : }
373 : }
374 :
375 : /// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
376 : ///
377 : /// template-parameter: [C++ temp.param]
378 : /// type-parameter
379 : /// parameter-declaration
380 : ///
381 : /// type-parameter: (see below)
382 : /// 'class' ...[opt][C++0x] identifier[opt]
383 : /// 'class' identifier[opt] '=' type-id
384 : /// 'typename' ...[opt][C++0x] identifier[opt]
385 : /// 'typename' identifier[opt] '=' type-id
386 : /// 'template' ...[opt][C++0x] '<' template-parameter-list '>' 'class' identifier[opt]
387 : /// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
388 : Parser::DeclPtrTy
389 2165: Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
1713: branch 1 taken
452: branch 2 taken
390 2165: if (isStartOfTemplateTypeParameter())
391 1713: return ParseTypeParameter(Depth, Position);
392 :
59: branch 1 taken
393: branch 2 taken
393 452: if (Tok.is(tok::kw_template))
394 59: return ParseTemplateTemplateParameter(Depth, Position);
395 :
396 : // If it's none of the above, then it must be a parameter declaration.
397 : // NOTE: This will pick up errors in the closure of the template parameter
398 : // list (e.g., template < ; Check here to implement >> style closures.
399 393: return ParseNonTypeTemplateParameter(Depth, Position);
400 : }
401 :
402 : /// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
403 : /// Other kinds of template parameters are parsed in
404 : /// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
405 : ///
406 : /// type-parameter: [C++ temp.param]
407 : /// 'class' ...[opt][C++0x] identifier[opt]
408 : /// 'class' identifier[opt] '=' type-id
409 : /// 'typename' ...[opt][C++0x] identifier[opt]
410 : /// 'typename' identifier[opt] '=' type-id
411 1713: Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
412 : assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
1391: branch 1 taken
322: branch 2 taken
1391: branch 4 taken
0: branch 5 not taken
413 1713: "A type-parameter starts with 'class' or 'typename'");
414 :
415 : // Consume the 'class' or 'typename' keyword.
416 1713: bool TypenameKeyword = Tok.is(tok::kw_typename);
417 1713: SourceLocation KeyLoc = ConsumeToken();
418 :
419 : // Grab the ellipsis (if given).
420 1713: bool Ellipsis = false;
421 1713: SourceLocation EllipsisLoc;
8: branch 1 taken
1705: branch 2 taken
422 1713: if (Tok.is(tok::ellipsis)) {
423 8: Ellipsis = true;
424 8: EllipsisLoc = ConsumeToken();
425 :
1: branch 1 taken
7: branch 2 taken
426 8: if (!getLang().CPlusPlus0x)
427 1: Diag(EllipsisLoc, diag::err_variadic_templates);
428 : }
429 :
430 : // Grab the template parameter name (if given)
431 1713: SourceLocation NameLoc;
432 1713: IdentifierInfo* ParamName = 0;
1620: branch 1 taken
93: branch 2 taken
433 1713: if (Tok.is(tok::identifier)) {
434 1620: ParamName = Tok.getIdentifierInfo();
435 1620: NameLoc = ConsumeToken();
90: branch 1 taken
3: branch 2 taken
70: branch 4 taken
20: branch 5 taken
70: branch 7 taken
0: branch 8 not taken
0: branch 9 not taken
93: branch 10 taken
436 93: } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
437 : Tok.is(tok::greater)) {
438 : // Unnamed template parameter. Don't have to do anything here, just
439 : // don't consume this token.
440 : } else {
441 0: Diag(Tok.getLocation(), diag::err_expected_ident);
442 0: return DeclPtrTy();
443 : }
444 :
445 : DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
446 : Ellipsis, EllipsisLoc,
447 : KeyLoc, ParamName, NameLoc,
448 1713: Depth, Position);
449 :
450 : // Grab a default type id (if given).
49: branch 1 taken
1664: branch 2 taken
451 1713: if (Tok.is(tok::equal)) {
452 49: SourceLocation EqualLoc = ConsumeToken();
453 49: SourceLocation DefaultLoc = Tok.getLocation();
454 49: TypeResult DefaultType = ParseTypeName();
49: branch 1 taken
0: branch 2 not taken
455 49: if (!DefaultType.isInvalid())
456 : Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
457 49: DefaultType.get());
458 : }
459 :
460 1713: return TypeParam;
461 : }
462 :
463 : /// ParseTemplateTemplateParameter - Handle the parsing of template
464 : /// template parameters.
465 : ///
466 : /// type-parameter: [C++ temp.param]
467 : /// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
468 : /// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
469 : Parser::DeclPtrTy
470 59: Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
59: branch 1 taken
0: branch 2 not taken
471 59: assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
472 :
473 : // Handle the template <...> part.
474 59: SourceLocation TemplateLoc = ConsumeToken();
475 59: TemplateParameterList TemplateParams;
476 59: SourceLocation LAngleLoc, RAngleLoc;
477 : {
478 59: ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
1: branch 1 taken
58: branch 2 taken
479 59: if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
480 : RAngleLoc)) {
481 1: return DeclPtrTy();
58: branch 1 taken
1: branch 2 taken
482 59: }
483 : }
484 :
485 : // Generate a meaningful error if the user forgot to put class before the
486 : // identifier, comma, or greater.
2: branch 1 taken
56: branch 2 taken
487 58: if (!Tok.is(tok::kw_class)) {
488 : Diag(Tok.getLocation(), diag::err_expected_class_before)
489 2: << PP.getSpelling(Tok);
490 2: return DeclPtrTy();
491 : }
492 56: SourceLocation ClassLoc = ConsumeToken();
493 :
494 : // Get the identifier, if given.
495 56: SourceLocation NameLoc;
496 56: IdentifierInfo* ParamName = 0;
36: branch 1 taken
20: branch 2 taken
497 56: if (Tok.is(tok::identifier)) {
498 36: ParamName = Tok.getIdentifierInfo();
499 36: NameLoc = ConsumeToken();
13: branch 1 taken
7: branch 2 taken
7: branch 4 taken
6: branch 5 taken
7: branch 7 taken
0: branch 8 not taken
0: branch 9 not taken
20: branch 10 taken
500 20: } else if (Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
501 : // Unnamed template parameter. Don't have to do anything here, just
502 : // don't consume this token.
503 : } else {
504 0: Diag(Tok.getLocation(), diag::err_expected_ident);
505 0: return DeclPtrTy();
506 : }
507 :
508 : TemplateParamsTy *ParamList =
509 : Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
510 : TemplateLoc, LAngleLoc,
511 : &TemplateParams[0],
512 : TemplateParams.size(),
513 56: RAngleLoc);
514 :
515 : Parser::DeclPtrTy Param
516 : = Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
517 : ParamList, ParamName,
518 56: NameLoc, Depth, Position);
519 :
520 : // Get the a default value, if given.
14: branch 1 taken
42: branch 2 taken
521 56: if (Tok.is(tok::equal)) {
522 14: SourceLocation EqualLoc = ConsumeToken();
523 14: ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
3: branch 1 taken
11: branch 2 taken
524 14: if (Default.isInvalid()) {
525 : Diag(Tok.getLocation(),
526 3: diag::err_default_template_template_parameter_not_template);
527 : static const tok::TokenKind EndToks[] = {
528 : tok::comma, tok::greater, tok::greatergreater
529 : };
530 3: SkipUntil(EndToks, 3, true, true);
531 3: return Param;
11: branch 1 taken
0: branch 2 not taken
532 11: } else if (Param)
533 11: Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
534 : }
535 :
536 53: return Param;
537 : }
538 :
539 : /// ParseNonTypeTemplateParameter - Handle the parsing of non-type
540 : /// template parameters (e.g., in "template<int Size> class array;").
541 : ///
542 : /// template-parameter:
543 : /// ...
544 : /// parameter-declaration
545 : ///
546 : /// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
547 : /// but that didn't work out to well. Instead, this tries to recrate the basic
548 : /// parsing of parameter declarations, but tries to constrain it for template
549 : /// parameters.
550 : /// FIXME: We need to make a ParseParameterDeclaration that works for
551 : /// non-type template parameters and normal function parameters.
552 : Parser::DeclPtrTy
553 393: Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
554 393: SourceLocation StartLoc = Tok.getLocation();
555 :
556 : // Parse the declaration-specifiers (i.e., the type).
557 : // FIXME: The type should probably be restricted in some way... Not all
558 : // declarators (parts of declarators?) are accepted for parameters.
559 393: DeclSpec DS;
560 393: ParseDeclarationSpecifiers(DS);
561 :
562 : // Parse this as a typename.
563 393: Declarator ParamDecl(DS, Declarator::TemplateParamContext);
564 393: ParseDeclarator(ParamDecl);
1: branch 1 taken
392: branch 2 taken
1: branch 4 taken
0: branch 5 not taken
1: branch 6 taken
392: branch 7 taken
565 393: if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
566 : // This probably shouldn't happen - and it's more of a Sema thing, but
567 : // basically we didn't parse the type name because we couldn't associate
568 : // it with an AST node. we should just skip to the comma or greater.
569 : // TODO: This is currently a placeholder for some kind of Sema Error.
570 1: Diag(Tok.getLocation(), diag::err_parse_error);
571 1: SkipUntil(tok::comma, tok::greater, true, true);
572 1: return DeclPtrTy();
573 : }
574 :
575 : // Create the parameter.
576 : DeclPtrTy Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
577 392: Depth, Position);
578 :
579 : // If there is a default value, parse it.
23: branch 1 taken
369: branch 2 taken
580 392: if (Tok.is(tok::equal)) {
581 23: SourceLocation EqualLoc = ConsumeToken();
582 :
583 : // C++ [temp.param]p15:
584 : // When parsing a default template-argument for a non-type
585 : // template-parameter, the first non-nested > is taken as the
586 : // end of the template-parameter-list rather than a greater-than
587 : // operator.
588 23: GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
589 :
590 23: OwningExprResult DefaultArg = ParseAssignmentExpression();
0: branch 1 not taken
23: branch 2 taken
591 23: if (DefaultArg.isInvalid())
592 0: SkipUntil(tok::comma, tok::greater, true, true);
23: branch 1 taken
0: branch 2 not taken
593 23: else if (Param)
594 : Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
595 23: move(DefaultArg));
596 : }
597 :
598 392: return Param;
599 : }
600 :
601 : /// \brief Parses a template-id that after the template name has
602 : /// already been parsed.
603 : ///
604 : /// This routine takes care of parsing the enclosed template argument
605 : /// list ('<' template-parameter-list [opt] '>') and placing the
606 : /// results into a form that can be transferred to semantic analysis.
607 : ///
608 : /// \param Template the template declaration produced by isTemplateName
609 : ///
610 : /// \param TemplateNameLoc the source location of the template name
611 : ///
612 : /// \param SS if non-NULL, the nested-name-specifier preceding the
613 : /// template name.
614 : ///
615 : /// \param ConsumeLastToken if true, then we will consume the last
616 : /// token that forms the template-id. Otherwise, we will leave the
617 : /// last token in the stream (e.g., so that it can be replaced with an
618 : /// annotation token).
619 : bool
620 : Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
621 : SourceLocation TemplateNameLoc,
622 : const CXXScopeSpec *SS,
623 : bool ConsumeLastToken,
624 : SourceLocation &LAngleLoc,
625 : TemplateArgList &TemplateArgs,
626 2548: SourceLocation &RAngleLoc) {
2548: branch 1 taken
0: branch 2 not taken
627 2548: assert(Tok.is(tok::less) && "Must have already parsed the template-name");
628 :
629 : // Consume the '<'.
630 2548: LAngleLoc = ConsumeToken();
631 :
632 : // Parse the optional template-argument-list.
633 2548: bool Invalid = false;
634 : {
635 2548: GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
2515: branch 1 taken
33: branch 2 taken
636 2548: if (Tok.isNot(tok::greater))
637 2515: Invalid = ParseTemplateArgumentList(TemplateArgs);
638 :
3: branch 0 taken
2545: branch 1 taken
639 2548: if (Invalid) {
640 : // Try to find the closing '>'.
641 3: SkipUntil(tok::greater, true, !ConsumeLastToken);
642 :
643 6: return true;
2545: branch 1 taken
3: branch 2 taken
644 2548: }
645 : }
646 :
13: branch 1 taken
2532: branch 2 taken
2: branch 4 taken
11: branch 5 taken
2: branch 6 taken
2543: branch 7 taken
647 2558: if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) {
648 2: Diag(Tok.getLocation(), diag::err_expected_greater);
649 2: return true;
650 : }
651 :
652 : // Determine the location of the '>' or '>>'. Only consume this
653 : // token if the caller asked us to.
654 2543: RAngleLoc = Tok.getLocation();
655 :
11: branch 1 taken
2532: branch 2 taken
656 2543: if (Tok.is(tok::greatergreater)) {
3: branch 1 taken
8: branch 2 taken
657 11: if (!getLang().CPlusPlus0x) {
658 3: const char *ReplaceStr = "> >";
3: branch 2 taken
0: branch 3 not taken
1: branch 6 taken
2: branch 7 taken
1: branch 8 taken
2: branch 9 taken
659 3: if (NextToken().is(tok::greater) || NextToken().is(tok::greatergreater))
660 1: ReplaceStr = "> > ";
661 :
662 : Diag(Tok.getLocation(), diag::err_two_right_angle_brackets_need_space)
663 : << CodeModificationHint::CreateReplacement(
664 3: SourceRange(Tok.getLocation()), ReplaceStr);
665 : }
666 :
667 11: Tok.setKind(tok::greater);
11: branch 0 taken
0: branch 1 not taken
668 11: if (!ConsumeLastToken) {
669 : // Since we're not supposed to consume the '>>' token, we need
670 : // to insert a second '>' token after the first.
671 11: PP.EnterToken(Tok);
672 : }
7: branch 0 taken
2525: branch 1 taken
673 2532: } else if (ConsumeLastToken)
674 7: ConsumeToken();
675 :
676 2543: return false;
677 : }
678 :
679 : /// \brief Replace the tokens that form a simple-template-id with an
680 : /// annotation token containing the complete template-id.
681 : ///
682 : /// The first token in the stream must be the name of a template that
683 : /// is followed by a '<'. This routine will parse the complete
684 : /// simple-template-id and replace the tokens with a single annotation
685 : /// token with one of two different kinds: if the template-id names a
686 : /// type (and \p AllowTypeAnnotation is true), the annotation token is
687 : /// a type annotation that includes the optional nested-name-specifier
688 : /// (\p SS). Otherwise, the annotation token is a template-id
689 : /// annotation that does not include the optional
690 : /// nested-name-specifier.
691 : ///
692 : /// \param Template the declaration of the template named by the first
693 : /// token (an identifier), as returned from \c Action::isTemplateName().
694 : ///
695 : /// \param TemplateNameKind the kind of template that \p Template
696 : /// refers to, as returned from \c Action::isTemplateName().
697 : ///
698 : /// \param SS if non-NULL, the nested-name-specifier that precedes
699 : /// this template name.
700 : ///
701 : /// \param TemplateKWLoc if valid, specifies that this template-id
702 : /// annotation was preceded by the 'template' keyword and gives the
703 : /// location of that keyword. If invalid (the default), then this
704 : /// template-id was not preceded by a 'template' keyword.
705 : ///
706 : /// \param AllowTypeAnnotation if true (the default), then a
707 : /// simple-template-id that refers to a class template, template
708 : /// template parameter, or other template that produces a type will be
709 : /// replaced with a type annotation token. Otherwise, the
710 : /// simple-template-id is always replaced with a template-id
711 : /// annotation token.
712 : ///
713 : /// If an unrecoverable parse error occurs and no annotation token can be
714 : /// formed, this function returns true.
715 : ///
716 : bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
717 : const CXXScopeSpec *SS,
718 : UnqualifiedId &TemplateName,
719 : SourceLocation TemplateKWLoc,
720 2541: bool AllowTypeAnnotation) {
2541: branch 1 taken
0: branch 2 not taken
721 2541: assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
722 : assert(Template && Tok.is(tok::less) &&
2541: branch 1 taken
0: branch 2 not taken
2541: branch 4 taken
0: branch 5 not taken
723 5082: "Parser isn't at the beginning of a template-id");
724 :
725 : // Consume the template-name.
726 2541: SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();
727 :
728 : // Parse the enclosed template argument list.
729 2541: SourceLocation LAngleLoc, RAngleLoc;
730 2541: TemplateArgList TemplateArgs;
731 : bool Invalid = ParseTemplateIdAfterTemplateName(Template,
732 : TemplateNameLoc,
733 : SS, false, LAngleLoc,
734 : TemplateArgs,
735 2541: RAngleLoc);
736 :
5: branch 0 taken
2536: branch 1 taken
737 2541: if (Invalid) {
738 : // If we failed to parse the template ID but skipped ahead to a >, we're not
739 : // going to be able to form a token annotation. Eat the '>' if present.
3: branch 1 taken
2: branch 2 taken
740 5: if (Tok.is(tok::greater))
741 3: ConsumeToken();
742 5: return true;
743 : }
744 :
745 : ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
746 2536: TemplateArgs.size());
747 :
748 : // Build the annotation token.
2270: branch 0 taken
266: branch 1 taken
0: branch 2 not taken
2270: branch 3 taken
749 2536: if (TNK == TNK_Type_template && AllowTypeAnnotation) {
750 : Action::TypeResult Type
751 : = Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
752 : LAngleLoc, TemplateArgsPtr,
753 0: RAngleLoc);
0: branch 1 not taken
0: branch 2 not taken
754 0: if (Type.isInvalid()) {
755 : // If we failed to parse the template ID but skipped ahead to a >, we're not
756 : // going to be able to form a token annotation. Eat the '>' if present.
0: branch 1 not taken
0: branch 2 not taken
757 0: if (Tok.is(tok::greater))
758 0: ConsumeToken();
759 0: return true;
760 : }
761 :
762 0: Tok.setKind(tok::annot_typename);
763 0: Tok.setAnnotationValue(Type.get());
0: branch 0 not taken
0: branch 1 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
764 0: if (SS && SS->isNotEmpty())
765 0: Tok.setLocation(SS->getBeginLoc());
0: branch 1 not taken
0: branch 2 not taken
766 0: else if (TemplateKWLoc.isValid())
767 0: Tok.setLocation(TemplateKWLoc);
768 : else
769 0: Tok.setLocation(TemplateNameLoc);
770 : } else {
771 : // Build a template-id annotation token that can be processed
772 : // later.
773 2536: Tok.setKind(tok::annot_template_id);
774 : TemplateIdAnnotation *TemplateId
775 2536: = TemplateIdAnnotation::Allocate(TemplateArgs.size());
776 2536: TemplateId->TemplateNameLoc = TemplateNameLoc;
2534: branch 1 taken
2: branch 2 taken
777 2536: if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
778 2534: TemplateId->Name = TemplateName.Identifier;
779 2534: TemplateId->Operator = OO_None;
780 : } else {
781 2: TemplateId->Name = 0;
782 2: TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
783 : }
784 2536: TemplateId->Template = Template.getAs<void*>();
785 2536: TemplateId->Kind = TNK;
786 2536: TemplateId->LAngleLoc = LAngleLoc;
787 2536: TemplateId->RAngleLoc = RAngleLoc;
788 2536: ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
3132: branch 1 taken
2536: branch 2 taken
789 5668: for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
790 3132: Args[Arg] = TemplateArgs[Arg];
791 2536: Tok.setAnnotationValue(TemplateId);
44: branch 1 taken
2492: branch 2 taken
792 2536: if (TemplateKWLoc.isValid())
793 44: Tok.setLocation(TemplateKWLoc);
794 : else
795 2492: Tok.setLocation(TemplateNameLoc);
796 :
797 2536: TemplateArgsPtr.release();
798 : }
799 :
800 : // Common fields for the annotation token
801 2536: Tok.setAnnotationEndLoc(RAngleLoc);
802 :
803 : // In case the tokens were cached, have Preprocessor replace them with the
804 : // annotation token.
805 2536: PP.AnnotateCachedTokens(Tok);
806 2536: return false;
807 : }
808 :
809 : /// \brief Replaces a template-id annotation token with a type
810 : /// annotation token.
811 : ///
812 : /// If there was a failure when forming the type from the template-id,
813 : /// a type annotation token will still be created, but will have a
814 : /// NULL type pointer to signify an error.
815 1860: void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
1860: branch 1 taken
0: branch 2 not taken
816 1860: assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
817 :
818 : TemplateIdAnnotation *TemplateId
819 1860: = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
820 : assert((TemplateId->Kind == TNK_Type_template ||
821 : TemplateId->Kind == TNK_Dependent_template_name) &&
39: branch 0 taken
1821: branch 1 taken
0: branch 2 not taken
39: branch 3 taken
822 1899: "Only works for type and dependent templates");
823 :
824 : ASTTemplateArgsPtr TemplateArgsPtr(Actions,
825 : TemplateId->getTemplateArgs(),
826 1860: TemplateId->NumArgs);
827 :
828 : Action::TypeResult Type
829 : = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
830 : TemplateId->TemplateNameLoc,
831 : TemplateId->LAngleLoc,
832 : TemplateArgsPtr,
833 1860: TemplateId->RAngleLoc);
834 : // Create the new "type" annotation token.
835 1860: Tok.setKind(tok::annot_typename);
54: branch 1 taken
1806: branch 2 taken
836 1860: Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
1407: branch 0 taken
453: branch 1 taken
216: branch 3 taken
1191: branch 4 taken
216: branch 5 taken
1644: branch 6 taken
837 1860: if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
838 216: Tok.setLocation(SS->getBeginLoc());
839 : // End location stays the same
840 :
841 : // Replace the template-id annotation token, and possible the scope-specifier
842 : // that precedes it, with the typename annotation token.
843 1860: PP.AnnotateCachedTokens(Tok);
844 1860: TemplateId->Destroy();
845 1860: }
846 :
847 : /// \brief Determine whether the given token can end a template argument.
848 200: static bool isEndOfTemplateArgument(Token Tok) {
849 : return Tok.is(tok::comma) || Tok.is(tok::greater) ||
171: branch 1 taken
29: branch 2 taken
18: branch 4 taken
153: branch 5 taken
0: branch 7 not taken
18: branch 8 taken
850 200: Tok.is(tok::greatergreater);
851 : }
852 :
853 : /// \brief Parse a C++ template template argument.
854 566: ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
376: branch 1 taken
190: branch 2 taken
375: branch 4 taken
1: branch 5 taken
365: branch 7 taken
10: branch 8 taken
365: branch 9 taken
201: branch 10 taken
855 566: if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
856 : !Tok.is(tok::annot_cxxscope))
857 365: return ParsedTemplateArgument();
858 :
859 : // C++0x [temp.arg.template]p1:
860 : // A template-argument for a template template-parameter shall be the name
861 : // of a class template or a template alias, expressed as id-expression.
862 : //
863 : // We parse an id-expression that refers to a class template or template
864 : // alias. The grammar we parse is:
865 : //
866 : // nested-name-specifier[opt] template[opt] identifier
867 : //
868 : // followed by a token that terminates a template argument, such as ',',
869 : // '>', or (in some cases) '>>'.
870 201: CXXScopeSpec SS; // nested-name-specifier, if present
871 : ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
872 201: /*EnteringContext=*/false);
873 :
12: branch 1 taken
189: branch 2 taken
1: branch 4 taken
11: branch 5 taken
1: branch 6 taken
200: branch 7 taken
874 201: if (SS.isSet() && Tok.is(tok::kw_template)) {
875 : // Parse the optional 'template' keyword following the
876 : // nested-name-specifier.
877 1: SourceLocation TemplateLoc = ConsumeToken();
878 :
1: branch 1 taken
0: branch 2 not taken
879 1: if (Tok.is(tok::identifier)) {
880 : // We appear to have a dependent template name.
881 1: UnqualifiedId Name;
882 1: Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
883 1: ConsumeToken(); // the identifier
884 :
885 : // If the next token signals the end of a template argument,
886 : // then we have a dependent template name that could be a template
887 : // template argument.
1: branch 1 taken
0: branch 2 not taken
888 1: if (isEndOfTemplateArgument(Tok)) {
889 : TemplateTy Template
890 : = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
891 : /*ObjectType=*/0,
892 1: /*EnteringContext=*/false);
1: branch 1 taken
0: branch 2 not taken
893 1: if (Template.get())
894 2: return ParsedTemplateArgument(SS, Template, Name.StartLocation);
0: branch 1 not taken
1: branch 2 taken
895 1: }
896 : }
199: branch 1 taken
1: branch 2 taken
897 200: } else if (Tok.is(tok::identifier)) {
898 : // We may have a (non-dependent) template name.
899 199: TemplateTy Template;
900 199: UnqualifiedId Name;
901 199: Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
902 199: ConsumeToken(); // the identifier
903 :
181: branch 1 taken
18: branch 2 taken
904 199: if (isEndOfTemplateArgument(Tok)) {
905 : TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
906 : /*ObjectType=*/0,
907 : /*EnteringContext=*/false,
908 181: Template);
181: branch 0 taken
0: branch 1 not taken
45: branch 2 taken
136: branch 3 taken
909 181: if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
910 : // We have an id-expression that refers to a class template or
911 : // (C++0x) template alias.
912 90: return ParsedTemplateArgument(SS, Template, Name.StartLocation);
913 : }
154: branch 1 taken
45: branch 2 taken
914 199: }
915 : }
916 :
917 : // We don't have a template template argument.
918 155: return ParsedTemplateArgument();
919 : }
920 :
921 : /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
922 : ///
923 : /// template-argument: [C++ 14.2]
924 : /// constant-expression
925 : /// type-id
926 : /// id-expression
927 3145: ParsedTemplateArgument Parser::ParseTemplateArgument() {
928 : // C++ [temp.arg]p2:
929 : // In a template-argument, an ambiguity between a type-id and an
930 : // expression is resolved to a type-id, regardless of the form of
931 : // the corresponding template-parameter.
932 : //
933 : // Therefore, we initially try to parse a type-id.
2593: branch 1 taken
552: branch 2 taken
934 3145: if (isCXXTypeId(TypeIdAsTemplateArgument)) {
935 2593: SourceLocation Loc = Tok.getLocation();
936 2593: TypeResult TypeArg = ParseTypeName();
2: branch 1 taken
2591: branch 2 taken
937 2593: if (TypeArg.isInvalid())
938 2: return ParsedTemplateArgument();
939 :
940 : return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
941 2591: Loc);
942 : }
943 :
944 : // Try to parse a template template argument.
945 : {
946 552: TentativeParsingAction TPA(*this);
947 :
948 : ParsedTemplateArgument TemplateTemplateArgument
949 552: = ParseTemplateTemplateArgument();
35: branch 1 taken
517: branch 2 taken
950 552: if (!TemplateTemplateArgument.isInvalid()) {
951 35: TPA.Commit();
952 70: return TemplateTemplateArgument;
953 : }
954 :
955 : // Revert this tentative parse to parse a non-type template argument.
517: branch 2 taken
35: branch 3 taken
956 517: TPA.Revert();
957 : }
958 :
959 : // Parse a non-type template argument.
960 517: SourceLocation Loc = Tok.getLocation();
961 517: OwningExprResult ExprArg = ParseConstantExpression();
516: branch 1 taken
1: branch 2 taken
0: branch 4 not taken
516: branch 5 taken
1: branch 6 taken
516: branch 7 taken
962 1033: if (ExprArg.isInvalid() || !ExprArg.get())
963 1: return ParsedTemplateArgument();
964 :
965 : return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
966 516: ExprArg.release(), Loc);
967 : }
968 :
969 : /// ParseTemplateArgumentList - Parse a C++ template-argument-list
970 : /// (C++ [temp.names]). Returns true if there was an error.
971 : ///
972 : /// template-argument-list: [C++ 14.2]
973 : /// template-argument
974 : /// template-argument-list ',' template-argument
975 : bool
976 3145: Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
977 630: while (true) {
978 3145: ParsedTemplateArgument Arg = ParseTemplateArgument();
3: branch 1 taken
3142: branch 2 taken
979 3145: if (Arg.isInvalid()) {
980 3: SkipUntil(tok::comma, tok::greater, true, true);
981 3: return true;
982 : }
983 :
984 : // Save this template argument.
985 3142: TemplateArgs.push_back(Arg);
986 :
987 : // If the next token is a comma, consume it and keep reading
988 : // arguments.
630: branch 1 taken
2512: branch 2 taken
989 3142: if (Tok.isNot(tok::comma)) break;
990 :
991 : // Consume the comma.
992 630: ConsumeToken();
993 : }
994 :
995 2512: return false;
996 : }
997 :
998 : /// \brief Parse a C++ explicit template instantiation
999 : /// (C++ [temp.explicit]).
1000 : ///
1001 : /// explicit-instantiation:
1002 : /// 'extern' [opt] 'template' declaration
1003 : ///
1004 : /// Note that the 'extern' is a GNU extension and C++0x feature.
1005 : Parser::DeclPtrTy
1006 : Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
1007 : SourceLocation TemplateLoc,
1008 377: SourceLocation &DeclEnd) {
1009 : return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
1010 : ParsedTemplateInfo(ExternLoc,
1011 : TemplateLoc),
1012 377: DeclEnd, AS_none);
1013 : }
Generated: 2010-02-10 01:31 by zcov