[cfe-commits] r97589 - in /cfe/trunk: lib/CodeGen/CodeGenModule.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/implicit-virtual-member-functions.cpp test/SemaTemplate/virtual-member-functions.cpp

Rafael Espindola rafael.espindola at gmail.com
Tue Mar 2 13:28:26 PST 2010


Author: rafael
Date: Tue Mar  2 15:28:26 2010
New Revision: 97589

URL: http://llvm.org/viewvc/llvm-project?rev=97589&view=rev
Log:
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.


Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp
    cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=97589&r1=97588&r2=97589&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Mar  2 15:28:26 2010
@@ -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);
+      }
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=97589&r1=97588&r2=97589&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar  2 15:28:26 2010
@@ -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;
-  
+    return false;
+
+  // Ignore declarations that are not definitions.
+  if (!MD->isThisDeclarationADefinition())
+    return false;
+
   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;
+  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);
   }
 }
-

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=97589&r1=97588&r2=97589&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar  2 15:28:26 2010
@@ -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.

Modified: cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp?rev=97589&r1=97588&r2=97589&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp (original)
+++ cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp Tue Mar  2 15:28:26 2010
@@ -15,9 +15,9 @@
 struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}}
   C();
   void operator delete(void *, int); // expected-note {{'operator delete' declared here}}
-}; // expected-note {{implicit default destructor for 'struct C' first required here}}
+};
 
-C::C() { }
+C::C() { }  // expected-note {{implicit default destructor for 'struct C' first required here}}
 
 struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}}
   void operator delete(void *, int); // expected-note {{'operator delete' declared here}}

Modified: cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp?rev=97589&r1=97588&r2=97589&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp (original)
+++ cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp Tue Mar  2 15:28:26 2010
@@ -14,7 +14,7 @@
 }
 
 void f(A<int> x) {
-  x.anchor();
+  x.anchor(); // expected-note{{in instantiation of member function 'PR5557::A<int>::anchor' requested here}}
 }
 
 template<typename T>
@@ -36,10 +36,10 @@
 
 template<typename T>
 struct Derived : Base<T> {
-  virtual void foo() { }
+  virtual void foo() { } // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}}
 };
 
-template struct Derived<int>; // expected-note{{instantiation}}
+template struct Derived<int>;
 
 template<typename T>
 struct HasOutOfLineKey {
@@ -52,4 +52,4 @@
   return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}}
 }
 
-HasOutOfLineKey<int> out_of_line;
+HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}}





More information about the cfe-commits mailing list