Handle -fdelayed-template-parsing of out-of-line definitions of

class template member classes (PR19613)

Also improve this code in general by implementing suggestions
from Richard.

Differential Revision: http://reviews.llvm.org/D3555?id=9020

llvm-svn: 207822
This commit is contained in:
Hans Wennborg 2014-05-02 02:01:07 +00:00
parent db2fc6d756
commit b6d4e8cd4e
4 changed files with 112 additions and 68 deletions

View File

@ -4884,8 +4884,7 @@ public:
void ActOnFinishCXXMemberDecls();
void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
void ActOnReenterTemplateScope(Scope *S, Decl *Template);
void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D);
unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template);
void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);

View File

@ -1239,7 +1239,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
// Get the list of DeclContexts to reenter.
SmallVector<DeclContext*, 4> DeclContextsToReenter;
DeclContext *DD = FunD->getLexicalParent();
DeclContext *DD = FunD;
while (DD && !DD->isTranslationUnit()) {
DeclContextsToReenter.push_back(DD);
DD = DD->getLexicalParent();
@ -1249,37 +1249,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
SmallVectorImpl<DeclContext *>::reverse_iterator II =
DeclContextsToReenter.rbegin();
for (; II != DeclContextsToReenter.rend(); ++II) {
if (ClassTemplatePartialSpecializationDecl *MD =
dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
Actions.ActOnReenterTemplateScope(getCurScope(), MD);
++CurTemplateDepthTracker;
} else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
bool IsClassTemplate = MD->getDescribedClassTemplate() != 0;
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope,
/*ManageScope*/IsClassTemplate));
Actions.ActOnReenterTemplateScope(getCurScope(),
MD->getDescribedClassTemplate());
if (IsClassTemplate)
++CurTemplateDepthTracker;
TemplateParamScopeStack.push_back(new ParseScope(this,
Scope::TemplateParamScope));
unsigned NumParamLists =
Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
CurTemplateDepthTracker.addDepth(NumParamLists);
if (*II != FunD) {
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
Actions.PushDeclContext(Actions.getCurScope(), *II);
}
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
Actions.PushDeclContext(Actions.getCurScope(), *II);
}
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
const unsigned DeclaratorNumTemplateParameterLists =
(Declarator ? Declarator->getNumTemplateParameterLists() : 0);
if (Declarator && DeclaratorNumTemplateParameterLists != 0) {
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
CurTemplateDepthTracker.addDepth(DeclaratorNumTemplateParameterLists);
}
Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
++CurTemplateDepthTracker;
assert(!LPT.Toks.empty() && "Empty body!");
@ -1314,7 +1293,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
assert((!isa<FunctionTemplateDecl>(LPT.D) ||
cast<FunctionTemplateDecl>(LPT.D)
->getTemplateParameters()
->getDepth() < TemplateParameterDepth) &&
->getDepth() == TemplateParameterDepth - 1) &&
"TemplateParameterDepth should be greater than the depth of "
"current template being instantiated!");
ParseFunctionStatementBody(LPT.D, FnScope);

View File

@ -5980,47 +5980,55 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
}
}
void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) {
unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
return;
return 0;
int NumParamList = D->getNumTemplateParameterLists();
for (int i = 0; i < NumParamList; i++) {
TemplateParameterList* Params = D->getTemplateParameterList(i);
for (TemplateParameterList::iterator Param = Params->begin(),
ParamEnd = Params->end();
Param != ParamEnd; ++Param) {
NamedDecl *Named = cast<NamedDecl>(*Param);
if (Named->getDeclName()) {
S->AddDecl(Named);
IdResolver.AddDecl(Named);
// The order of template parameters is not important here. All names
// get added to the same scope.
SmallVector<TemplateParameterList *, 4> ParameterLists;
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
ParameterLists.push_back(PSD->getTemplateParameters());
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
ParameterLists.push_back(DD->getTemplateParameterList(i));
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
ParameterLists.push_back(FTD->getTemplateParameters());
}
}
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
ParameterLists.push_back(TD->getTemplateParameterList(i));
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
ParameterLists.push_back(CTD->getTemplateParameters());
}
}
unsigned Count = 0;
for (TemplateParameterList *Params : ParameterLists) {
if (Params->size() > 0)
// Ignore explicit specializations; they don't contribute to the template
// depth.
++Count;
for (NamedDecl *Param : *Params) {
if (Param->getDeclName()) {
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
}
}
}
void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
return;
TemplateParameterList *Params = 0;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
Params = Template->getTemplateParameters();
else if (ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
Params = PartialSpec->getTemplateParameters();
else
return;
for (TemplateParameterList::iterator Param = Params->begin(),
ParamEnd = Params->end();
Param != ParamEnd; ++Param) {
NamedDecl *Named = cast<NamedDecl>(*Param);
if (Named->getDeclName()) {
S->AddDecl(Named);
IdResolver.AddDecl(Named);
}
}
return Count;
}
void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {

View File

@ -123,3 +123,61 @@ constexpr int Var = Fun(20);
template <typename T>
auto invalidTrailingRetType() -> Bogus {} // expected-error {{unknown type name 'Bogus'}}
namespace PR19613 {
struct HeapTypeConfig {
static void from_bitset();
};
template <class Config>
struct TypeImpl {
struct BitsetType;
static void Any() {
BitsetType::New();
}
};
template<class Config>
struct TypeImpl<Config>::BitsetType {
static void New() {
Config::from_bitset();
}
};
static void f() {
TypeImpl<HeapTypeConfig>::Any();
}
template<typename A> struct S {
template<typename B> struct T;
};
template<typename A> template<typename B> struct S<A>::T {
template<typename C, typename D> struct U;
template<typename C> struct U<C, C> {
template<typename E> static int f() {
return sizeof(A) + sizeof(B) + sizeof(C) + sizeof(E);
}
};
};
static void g() {
S<int>::T<int>::U<int,int>::f<int>();
}
template<typename T> struct SS {
template<typename U> struct X;
template<typename U> struct X<U*>;
};
template<typename T> template<typename U> struct SS<T>::X<U*> {
static int f() {
return sizeof(T) + sizeof(U);
}
};
static void h() {
SS<int>::X<int*>::f();
}
}