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. llvm-svn: 79955
This commit is contained in:
parent
6bc04bca68
commit
a3dff8e37a
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
@ -105,14 +130,16 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
|||
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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) { }
|
||||
|
|
Loading…
Reference in New Issue