]> granicus.if.org Git - clang/commitdiff
CodeGen may see out-of-line declarations of the various special member
authorDouglas Gregor <dgregor@apple.com>
Thu, 1 Oct 2009 20:44:19 +0000 (20:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 1 Oct 2009 20:44:19 +0000 (20:44 +0000)
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

lib/CodeGen/CodeGenFunction.cpp
test/CodeGenCXX/destructors.cpp

index 72009daef68c56e1bf27153fc1c7f5ef68959bbe..f9e54b75708f6fda4d92ae502f7bd6a5d50bd5ea 100644 (file)
@@ -239,28 +239,37 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD,
     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
       EmitDtorEpilogue(DD, GD.getDtorType());
     FinishFunction(S->getRBracLoc());
-  }
-  else
+  } else if (FD->isImplicit()) {
+    const CXXRecordDecl *ClassDecl =
+      cast<CXXRecordDecl>(FD->getDeclContext());
+    (void) ClassDecl;
     if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
-      const CXXRecordDecl *ClassDecl =
-        cast<CXXRecordDecl>(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<CXXDestructorDecl>(FD))
-    SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args);
-  else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-    if (MD->isCopyAssignment())
+    } else if (const CXXDestructorDecl *CD = dyn_cast<CXXDestructorDecl>(FD)) {
+      assert(!ClassDecl->hasUserDeclaredDestructor() &&
+             "Cannot synthesize a non-implicit destructor");
+      SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args);
+    } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(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.
index e8080577ff69de1664778a716fc5b6382d6a8a49..44d2b2936864f8c28562702ec2b2150325d625e5 100644 (file)
@@ -19,4 +19,12 @@ struct C {
   ~C();
 };
 
-C::~C() { }
\ No newline at end of file
+C::~C() { }
+
+// PR5084
+template<typename T>
+class A1 {
+  ~A1();
+};
+
+template<> A1<char>::~A1();