From: Douglas Gregor Date: Fri, 21 Aug 2009 22:43:28 +0000 (+0000) Subject: Refactor instantiation of destructors to use the common CXXMethodDecl X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=17e32f30e2d1eaf6639d3d4e2196a8d7c709fbac;p=clang 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 --- 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(D); - if (ConstructorD) { + if (CXXConstructorDecl *Constructor = dyn_cast(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(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 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(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 struct A { + A(T); + ~A(); + void f(T*); + operator T*(); + static T value; }; template void A::f(X*) { } template X A::value; + +template A::A(X) { value = 0; } + +template A::~A() { } + +template A::operator X*() { return 0; } \ No newline at end of file