]> granicus.if.org Git - clang/commitdiff
During codegen assert that any copy assignment, destructor or constructor that
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 2 Mar 2010 21:28:26 +0000 (21:28 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 2 Mar 2010 21:28:26 +0000 (21:28 +0000)
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

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

index 523661908814e867e8eb006912cb32c0e8d84695..91c7322c67679753807a23d2380daf33976ed96d 100644 (file)
@@ -752,14 +752,20 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
     // 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);
+      }
     }
   }
 
index 20a8303ba42f611a8681ba1cfbda29908a436f25..574b22502789847b6d2783452b209262df9d31be 100644 (file)
@@ -1638,8 +1638,22 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
       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 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
   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 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, CXXRecordDecl *RD) {
       MarkDeclarationReferenced(Loc, MD);
   }
 }
-
index 23d52adf91a1528a04f3932b6ffad2c255c190a8..5f4601961c8e597151f0c44b2a9810c76ecaf5b2 100644 (file)
@@ -426,6 +426,18 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
                                             : 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.
index 4ae9eae3b316d505588018f61e332b7370c1e861..1bb5adbb861f375ba42ee6e598937566c0a68cf5 100644 (file)
@@ -15,9 +15,9 @@ void B::f() { // expected-note {{implicit default destructor for 'struct B' firs
 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}}
index db243130bb3dd3089d36d81600eb94abb6a75828..58ac08c0b21b1935a3e89aea7d8fd0301a5defe1 100644 (file)
@@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) {
 }
 
 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 @@ struct Base {
 
 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 @@ T *HasOutOfLineKey<T>::f(float *fp) {
   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}}