Refactor instantiation of destructors to use the common CXXMethodDecl

code, fixing a problem where instantiations of out-of-line destructor
definitions would had the wrong lexical context.

Introduce tests for out-of-line definitions of the constructors,
destructors, and conversion functions of a class template partial
specialization.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79682 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-08-21 22:43:28 +00:00
Родитель c28bbc2d22
Коммит 17e32f30e2
2 изменённых файлов: 24 добавлений и 34 удалений

Просмотреть файл

@ -488,17 +488,23 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
CXXMethodDecl *Method = 0;
DeclarationName Name = D->getDeclName();
CXXConstructorDecl *ConstructorD = dyn_cast<CXXConstructorDecl>(D);
if (ConstructorD) {
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
Name = SemaRef.Context.DeclarationNames.getCXXConstructorName(
SemaRef.Context.getCanonicalType(ClassTy));
Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
ConstructorD->getLocation(),
Constructor->getLocation(),
Name, T,
ConstructorD->getDeclaratorInfo(),
ConstructorD->isExplicit(),
ConstructorD->isInline(), false);
Constructor->getDeclaratorInfo(),
Constructor->isExplicit(),
Constructor->isInline(), false);
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
Name = SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(ClassTy));
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
Destructor->getLocation(), Name,
T, Destructor->isInline(), false);
} else {
Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
D->getDeclName(), T, D->getDeclaratorInfo(),
@ -558,34 +564,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
Sema::LocalInstantiationScope Scope(SemaRef);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = InstantiateFunctionType(D, Params);
if (T.isNull())
return 0;
assert(Params.size() == 0 && "Destructor with parameters?");
// Build the instantiated destructor declaration.
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
CanQualType ClassTy =
SemaRef.Context.getCanonicalType(SemaRef.Context.getTypeDeclType(Record));
CXXDestructorDecl *Destructor
= CXXDestructorDecl::Create(SemaRef.Context, Record,
D->getLocation(),
SemaRef.Context.DeclarationNames.getCXXDestructorName(ClassTy),
T, D->isInline(), false);
Destructor->setInstantiationOfMemberFunction(D);
if (InitMethodInstantiation(Destructor, D))
Destructor->setInvalidDecl();
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
NamedDecl *PrevDecl = 0;
SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
Owner->addDecl(Destructor);
return Destructor;
return VisitCXXMethodDecl(D);
}
Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {

Просмотреть файл

@ -5,11 +5,22 @@ struct A;
template<typename T>
struct A<T*, 2> {
A(T);
~A();
void f(T*);
operator T*();
static T value;
};
template<class X> void A<X*, 2>::f(X*) { }
template<class X> X A<X*, 2>::value;
template<class X> A<X*, 2>::A(X) { value = 0; }
template<class X> A<X*, 2>::~A() { }
template<class X> A<X*, 2>::operator X*() { return 0; }