summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-08-21 22:43:28 +0000
committerDouglas Gregor <dgregor@apple.com>2009-08-21 22:43:28 +0000
commit17e32f30e2d1eaf6639d3d4e2196a8d7c709fbac (patch)
tree553e33d929d90b512d3e7b71ccd8a13f436dbd4e
parentc28bbc2d2271aab6c5d79ef2758604221cd92a4b (diff)
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
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp47
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp11
2 files changed, 24 insertions, 34 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9e05b3231e..ff97631e72 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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) {
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp
index 0321a7cfa3..bd9a06de31 100644
--- a/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp
+++ b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp
@@ -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; } \ No newline at end of file