During codegen assert that any copy assignment, destructor or constructor that
we need to synthesize has been marked as used by Sema.

Change Sema to avoid these asserts.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97589 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5236619..91c7322 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -752,14 +752,20 @@
     // A called constructor which has no definition or declaration need be
     // synthesized.
     else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
-      if (CD->isImplicit())
+      if (CD->isImplicit()) {
+        assert (CD->isUsed());
         DeferredDeclsToEmit.push_back(D);
+      }
     } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
-      if (DD->isImplicit())
+      if (DD->isImplicit()) {
+        assert (DD->isUsed());
         DeferredDeclsToEmit.push_back(D);
+      }
     } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-      if (MD->isCopyAssignment() && MD->isImplicit())
+      if (MD->isCopyAssignment() && MD->isImplicit()) {
+        assert (MD->isUsed());
         DeferredDeclsToEmit.push_back(D);
+      }
     }
   }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 20a8303..574b225 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1638,8 +1638,22 @@
       new (Context) CXXBaseOrMemberInitializer*[NumInitializers];
 
     Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers);
-    for (unsigned Idx = 0; Idx < NumInitializers; ++Idx)
-      baseOrMemberInitializers[Idx] = AllToInit[Idx];
+    for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) {
+      CXXBaseOrMemberInitializer *Member = AllToInit[Idx];
+      baseOrMemberInitializers[Idx] = Member;
+      if (!Member->isBaseInitializer())
+        continue;
+      const Type *BaseType = Member->getBaseClass();
+      const RecordType *RT = BaseType->getAs<RecordType>();
+      if (!RT)
+        continue;
+      CXXRecordDecl *BaseClassDecl =
+          cast<CXXRecordDecl>(RT->getDecl());
+      if (BaseClassDecl->hasTrivialDestructor())
+        continue;
+      CXXDestructorDecl *DD = BaseClassDecl->getDestructor(Context);
+      MarkDeclarationReferenced(Constructor->getLocation(), DD);
+    }
   }
 
   return HadError;
@@ -5791,55 +5805,74 @@
   return Dcl;
 }
 
-void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
-                                             CXXMethodDecl *MD) {
+static bool needsVtable(CXXMethodDecl *MD, ASTContext &Context) {
   // Ignore dependent types.
   if (MD->isDependentContext())
-    return;
-  
-  CXXRecordDecl *RD = MD->getParent();
-  
-  // Ignore classes without a vtable.
-  if (!RD->isDynamicClass())
-    return;
+    return false;
 
   // Ignore declarations that are not definitions.
   if (!MD->isThisDeclarationADefinition())
-    return;
-  
-  if (isa<CXXConstructorDecl>(MD)) {
-    switch (MD->getParent()->getTemplateSpecializationKind()) {
-    case TSK_Undeclared:
-    case TSK_ExplicitSpecialization:
-      // Classes that aren't instantiations of templates don't need their
-      // virtual methods marked until we see the definition of the key 
-      // function.
-      return;
-        
-    case TSK_ImplicitInstantiation:
-    case TSK_ExplicitInstantiationDeclaration:
-    case TSK_ExplicitInstantiationDefinition:
-      // This is a constructor of a class template; mark all of the virtual
-      // members as referenced to ensure that they get instantiatied.
-      break;
-    }
-  } else if (!MD->isOutOfLine()) {
-    // Consider only out-of-line definitions of member functions. When we see
-    // an inline definition, it's too early to compute the key function.
-    return;
-  } else if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD)) {
-    // If this is not the key function, we don't need to mark virtual members.
-    if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
-      return;
-  } else {
-    // The class has no key function, so we've already noted that we need to
-    // mark the virtual members of this class.
-    return;
+    return false;
+
+  CXXRecordDecl *RD = MD->getParent();
+
+  // Ignore classes without a vtable.
+  if (!RD->isDynamicClass())
+    return false;
+
+  switch (MD->getParent()->getTemplateSpecializationKind()) {
+  case TSK_Undeclared:
+  case TSK_ExplicitSpecialization:
+    // Classes that aren't instantiations of templates don't need their
+    // virtual methods marked until we see the definition of the key 
+    // function.
+    break;
+
+  case TSK_ImplicitInstantiation:
+    // This is a constructor of a class template; mark all of the virtual
+    // members as referenced to ensure that they get instantiatied.
+    if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+      return true;
+    break;
+
+  case TSK_ExplicitInstantiationDeclaration:
+    return true; //FIXME: This looks wrong.
+
+  case TSK_ExplicitInstantiationDefinition:
+    // This is method of a explicit instantiation; mark all of the virtual
+    // members as referenced to ensure that they get instantiatied.
+    return true;
   }
-  
+
+  // Consider only out-of-line definitions of member functions. When we see
+  // an inline definition, it's too early to compute the key function.
+  if (!MD->isOutOfLine())
+    return false;
+
+  const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
+
+  // If there is no key function, we will need a copy of the vtable.
+  if (!KeyFunction)
+    return true;
+
+  // If this is the key function, we need to mark virtual members.
+  if (KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl())
+    return true;
+
+  return false;
+}
+
+void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
+                                             CXXMethodDecl *MD) {
+  CXXRecordDecl *RD = MD->getParent();
+
   // We will need to mark all of the virtual members as referenced to build the
   // vtable.
-  ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
+  // We actually call MarkVirtualMembersReferenced instead of adding to
+  // ClassesWithUnmarkedVirtualMembers because this marking is needed by
+  // codegen that will happend before we finish parsing the file.
+  if (needsVtable(MD, Context))
+    MarkVirtualMembersReferenced(Loc, RD);
 }
 
 bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() {
@@ -5867,4 +5900,3 @@
       MarkDeclarationReferenced(Loc, MD);
   }
 }
-
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 23d52ad..5f46019 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -426,6 +426,18 @@
                                             : diag::err_throw_incomplete)
                               << E->getSourceRange()))
       return true;
+
+    // FIXME: This is just a hack to mark the copy constructor referenced.
+    // This should go away when the next FIXME is fixed.
+    const RecordType *RT = Ty->getAs<RecordType>();
+    if (!RT)
+      return false;
+
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+    if (RD->hasTrivialCopyConstructor())
+      return false;
+    CXXConstructorDecl *CopyCtor = RD->getCopyConstructor(Context, 0);
+    MarkDeclarationReferenced(ThrowLoc, CopyCtor);
   }
 
   // FIXME: Construct a temporary here.