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:
parent
db2fc6d756
commit
b6d4e8cd4e
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue