]> granicus.if.org Git - clang/commitdiff
Re-enable the fix for PR9181 now that all the edge cases are handled.
authorAnders Carlsson <andersca@mac.com>
Sun, 15 May 2011 17:36:21 +0000 (17:36 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 15 May 2011 17:36:21 +0000 (17:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131385 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
test/CodeGenCXX/mangle-subst-std.cpp
test/CodeGenCXX/skip-vtable-pointer-initialization.cpp

index 73dfc9fe7dbd8f0ae52a4d2a5561cfb3730063c6..8b4684cb38776a3b89e38b8bec1cfcb528b13ccf 100644 (file)
@@ -741,14 +741,78 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
     EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args);
 }
 
+static bool
+FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);
+
+static bool
+HasTrivialDestructorBody(ASTContext &Context, 
+                         const CXXRecordDecl *BaseClassDecl,
+                         const CXXRecordDecl *MostDerivedClassDecl)
+{
+  // If the destructor is trivial we don't have to check anything else.
+  if (BaseClassDecl->hasTrivialDestructor())
+    return true;
+
+  if (!BaseClassDecl->getDestructor()->hasTrivialBody())
+    return false;
+
+  // Check fields.
+  for (CXXRecordDecl::field_iterator I = BaseClassDecl->field_begin(),
+       E = BaseClassDecl->field_end(); I != E; ++I) {
+    const FieldDecl *Field = *I;
+    
+    if (!FieldHasTrivialDestructorBody(Context, Field))
+      return false;
+  }
+
+  // Check non-virtual bases.
+  for (CXXRecordDecl::base_class_const_iterator I = 
+       BaseClassDecl->bases_begin(), E = BaseClassDecl->bases_end();
+       I != E; ++I) {
+    if (I->isVirtual())
+      continue;
+
+    const CXXRecordDecl *NonVirtualBase =
+      cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
+    if (!HasTrivialDestructorBody(Context, NonVirtualBase,
+                                  MostDerivedClassDecl))
+      return false;
+  }
+
+  if (BaseClassDecl == MostDerivedClassDecl) {
+    // Check virtual bases.
+    for (CXXRecordDecl::base_class_const_iterator I = 
+         BaseClassDecl->vbases_begin(), E = BaseClassDecl->vbases_end();
+         I != E; ++I) {
+      const CXXRecordDecl *VirtualBase =
+        cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
+      if (!HasTrivialDestructorBody(Context, VirtualBase,
+                                    MostDerivedClassDecl))
+        return false;      
+    }
+  }
+
+  return true;
+}
+
+static bool
+FieldHasTrivialDestructorBody(ASTContext &Context,
+                              const FieldDecl *Field)
+{
+  QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldBaseElementType->getAs<RecordType>();
+  if (!RT)
+    return true;
+  
+  CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+  return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
+}
+
 /// CanSkipVTablePointerInitialization - Check whether we need to initialize
 /// any vtable pointers before calling this destructor.
 static bool CanSkipVTablePointerInitialization(ASTContext &Context,
                                            const CXXDestructorDecl *Dtor) {
-  // FIXME: We need to check dtors of bases of members too. 
-  // Re-enable once this has been fixed.
-  return false;
-
   if (!Dtor->hasTrivialBody())
     return false;
 
@@ -757,21 +821,9 @@ static bool CanSkipVTablePointerInitialization(ASTContext &Context,
   for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
        E = ClassDecl->field_end(); I != E; ++I) {
     const FieldDecl *Field = *I;
-    
-    QualType FieldBaseElementType = 
-      Context.getBaseElementType(Field->getType());
 
-    const RecordType *RT = FieldBaseElementType->getAs<RecordType>();
-    if (!RT)
-      continue;
-    
-    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-    if (FieldClassDecl->hasTrivialDestructor())
-      continue;
-    if (FieldClassDecl->getDestructor()->hasTrivialBody())
-      continue;
-
-    return false;
+    if (!FieldHasTrivialDestructorBody(Context, Field))
+      return false;
   }
 
   return true;
index fea3582d321a38efce41d5ee1d942eb753246d88..c54d3e5297f0e2d1cc1cd81dd656a2d394bc1bd1 100644 (file)
@@ -8,8 +8,8 @@
 // CHECK: @_ZTCSd0_Si = linkonce_odr unnamed_addr constant 
 // CHECK: @_ZTCSd16_So = linkonce_odr unnamed_addr constant
 // CHECK: @_ZTTSo = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTVSo = linkonce_odr unnamed_addr constant
 // CHECK: @_ZTTSi = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTVSo = linkonce_odr unnamed_addr constant
 // CHECK: @_ZTVSi = linkonce_odr unnamed_addr constant
 namespace std {
   struct A { A(); };
index 3b70ec03a3495c5830946f7bbd181084fe5d02f1..3520b912cf925a87b7c29da5cce95dccd6c4e3dd 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// XFAIL: *
 
 namespace Test1 {
 
@@ -104,4 +103,84 @@ A::~A()
 {
 }
 
-}
\ No newline at end of file
+}
+
+namespace Test6 {
+
+// Check that we do initialize the vtable pointer in A::~A(), since Field has a member
+// variable with a non-trivial destructor body.
+
+struct NonTrivialDestructorBody {
+  ~NonTrivialDestructorBody();
+};
+
+struct Field {
+  NonTrivialDestructorBody nonTrivialDestructorBody;
+};
+
+struct A {
+  virtual void f();
+  ~A();
+
+  Field field;
+};
+
+// CHECK: define void @_ZN5Test61AD2Ev
+// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2), i8***
+A::~A()
+{
+}
+
+}
+
+namespace Test7 {
+
+// Check that we do initialize the vtable pointer in A::~A(), since Field has a base
+// class with a non-trivial destructor body.
+
+struct NonTrivialDestructorBody {
+  ~NonTrivialDestructorBody();
+};
+
+struct Field : NonTrivialDestructorBody { };
+
+struct A {
+  virtual void f();
+  ~A();
+
+  Field field;
+};
+
+// CHECK: define void @_ZN5Test71AD2Ev
+// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2), i8***
+A::~A()
+{
+}
+
+}
+
+namespace Test8 {
+
+// Check that we do initialize the vtable pointer in A::~A(), since Field has a virtual base
+// class with a non-trivial destructor body.
+
+struct NonTrivialDestructorBody {
+  ~NonTrivialDestructorBody();
+};
+
+struct Field : virtual NonTrivialDestructorBody { };
+
+struct A {
+  virtual void f();
+  ~A();
+
+  Field field;
+};
+
+// CHECK: define void @_ZN5Test81AD2Ev
+// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2), i8***
+A::~A()
+{
+}
+
+}