From: Douglas Gregor Date: Thu, 1 Oct 2009 20:44:19 +0000 (+0000) Subject: CodeGen may see out-of-line declarations of the various special member X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4513272f444c59705123ccb6207414ce62c9a568;p=clang CodeGen may see out-of-line declarations of the various special member functions when they are explicitly declared, e.g., via a function template specialization or explicit template instantiation declaration. Don't try to synthesize bodies for the special member functions in this case; rather, check whether we have an implicit declaration and, if so, synthesize the appropriate function body. Fixes PR5084. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83212 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 72009daef6..f9e54b7570 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -239,28 +239,37 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, if (const CXXDestructorDecl *DD = dyn_cast(FD)) EmitDtorEpilogue(DD, GD.getDtorType()); FinishFunction(S->getRBracLoc()); - } - else + } else if (FD->isImplicit()) { + const CXXRecordDecl *ClassDecl = + cast(FD->getDeclContext()); + (void) ClassDecl; if (const CXXConstructorDecl *CD = dyn_cast(FD)) { - const CXXRecordDecl *ClassDecl = - cast(CD->getDeclContext()); - (void) ClassDecl; + // FIXME: For C++0x, we want to look for implicit *definitions* of + // these special member functions, rather than implicit *declarations*. if (CD->isCopyConstructor(getContext())) { assert(!ClassDecl->hasUserDeclaredCopyConstructor() && - "bogus constructor is being synthesize"); + "Cannot synthesize a non-implicit copy constructor"); SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args); - } - else { + } else if (CD->isDefaultConstructor()) { assert(!ClassDecl->hasUserDeclaredConstructor() && - "bogus constructor is being synthesize"); + "Cannot synthesize a non-implicit default constructor."); SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args); + } else { + assert(false && "Implicit constructor cannot be synthesized"); } - } - else if (const CXXDestructorDecl *CD = dyn_cast(FD)) - SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args); - else if (const CXXMethodDecl *MD = dyn_cast(FD)) { - if (MD->isCopyAssignment()) + } else if (const CXXDestructorDecl *CD = dyn_cast(FD)) { + assert(!ClassDecl->hasUserDeclaredDestructor() && + "Cannot synthesize a non-implicit destructor"); + SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args); + } else if (const CXXMethodDecl *MD = dyn_cast(FD)) { + assert(MD->isCopyAssignment() && + !ClassDecl->hasUserDeclaredCopyAssignment() && + "Cannot synthesize a method that is not an implicit-defined " + "copy constructor"); SynthesizeCXXCopyAssignment(MD, Fn, Args); + } else { + assert(false && "Cannot synthesize unknown implicit function"); + } } // Destroy the 'this' declaration. diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index e8080577ff..44d2b29368 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -19,4 +19,12 @@ struct C { ~C(); }; -C::~C() { } \ No newline at end of file +C::~C() { } + +// PR5084 +template +class A1 { + ~A1(); +}; + +template<> A1::~A1();