[cfe-commits] r131385 - in /cfe/trunk: lib/CodeGen/CGClass.cpp test/CodeGenCXX/mangle-subst-std.cpp test/CodeGenCXX/skip-vtable-pointer-initialization.cpp

Anders Carlsson andersca at mac.com
Sun May 15 10:36:21 PDT 2011


Author: andersca
Date: Sun May 15 12:36:21 2011
New Revision: 131385

URL: http://llvm.org/viewvc/llvm-project?rev=131385&view=rev
Log:
Re-enable the fix for PR9181 now that all the edge cases are handled.

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

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=131385&r1=131384&r2=131385&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Sun May 15 12:36:21 2011
@@ -741,14 +741,78 @@
     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 @@
   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;

Modified: cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp?rev=131385&r1=131384&r2=131385&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp Sun May 15 12:36:21 2011
@@ -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(); };

Modified: cfe/trunk/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp?rev=131385&r1=131384&r2=131385&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp Sun May 15 12:36:21 2011
@@ -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 @@
 {
 }
 
-}
\ 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()
+{
+}
+
+}





More information about the cfe-commits mailing list