diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-08-24 23:03:25 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-08-24 23:03:25 +0000 |
commit | c3058338075a2132e057f1249a13b55a81fe021c (patch) | |
tree | 350915cbf9c66e62dcd5ab5d44c9b235e045910e | |
parent | ac50213ec509063151bc1a9c6b7d71561896cdd5 (diff) |
Keep track of the template parameter depth properly when we have
member templates declared inside other templates. This allows us to
match out-of-line definitions of member function templates within
class templates to the declarations within the class template. We
still can't handle out-of-line definitions for member class templates,
however.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79955 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 3 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 37 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/nested-template.cpp | 14 |
4 files changed, 50 insertions, 6 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index ef8e48b7e6..9fd67b5d46 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -90,6 +90,9 @@ class Parser { /// argument list. bool GreaterThanIsOperator; + /// The "depth" of the template parameters currently being parsed. + unsigned TemplateParameterDepth; + /// \brief RAII object that makes '>' behave either as an operator /// or as the closing angle bracket for a template argument list. struct GreaterThanIsOperatorScope { diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index b2b7ed06e2..34cabfd7ad 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" +#include "llvm/Support/Compiler.h" using namespace clang; /// \brief Parse a template declaration, explicit instantiation, or @@ -29,6 +30,29 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context, return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS); } +/// \brief RAII class that manages the template parameter depth. +namespace { + class VISIBILITY_HIDDEN TemplateParameterDepthCounter { + unsigned &Depth; + unsigned AddedLevels; + + public: + explicit TemplateParameterDepthCounter(unsigned &Depth) + : Depth(Depth), AddedLevels(0) { } + + ~TemplateParameterDepthCounter() { + Depth -= AddedLevels; + } + + void operator++() { + ++Depth; + ++AddedLevels; + } + + operator unsigned() const { return Depth; } + }; +} + /// \brief Parse a template declaration or an explicit specialization. /// /// Template declarations include one or more template parameter lists @@ -77,6 +101,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // context). bool isSpecialization = true; TemplateParameterLists ParamLists; + TemplateParameterDepthCounter Depth(TemplateParameterDepth); do { // Consume the 'export', if any. SourceLocation ExportLoc; @@ -96,7 +121,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // Parse the '<' template-parameter-list '>' SourceLocation LAngleLoc, RAngleLoc; TemplateParameterList TemplateParams; - if (ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc, + if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a }. SkipUntil(tok::r_brace, true, true); @@ -104,15 +129,17 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, ConsumeToken(); return DeclPtrTy(); } - - if (!TemplateParams.empty()) - isSpecialization = false; ParamLists.push_back( - Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc, + Actions.ActOnTemplateParameterList(Depth, ExportLoc, TemplateLoc, LAngleLoc, TemplateParams.data(), TemplateParams.size(), RAngleLoc)); + + if (!TemplateParams.empty()) { + isSpecialization = false; + ++Depth; + } } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); // Parse the actual template declaration. diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 798af1840a..efaf1d5398 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -35,7 +35,7 @@ public: Parser::Parser(Preprocessor &pp, Action &actions) : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()), - GreaterThanIsOperator(true) { + TemplateParameterDepth(0), GreaterThanIsOperator(true) { Tok.setKind(tok::eof); CurScope = 0; NumCachedScopes = 0; diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp index 84b1d35ba9..9562bcb51e 100644 --- a/test/SemaTemplate/nested-template.cpp +++ b/test/SemaTemplate/nested-template.cpp @@ -14,3 +14,17 @@ public: int i; S::A<int>::Nested::type *ip = &i; +template<typename T> +struct X0 { + template<typename U> void f0(T, U); + + template<typename U> + struct Inner0 { + void f1(T, U); + }; +}; + +template<typename X> template<typename Y> void X0<X>::f0(X, Y) { } + +// FIXME: +// template<typename X> template<typename Y> void X0<X>::Inner0<Y>::f1(X, Y) { } |