]> granicus.if.org Git - clang/commitdiff
Look through array types when deciding whether a field requires non-trivial
authorJohn McCall <rjmccall@apple.com>
Sun, 13 Feb 2011 00:46:43 +0000 (00:46 +0000)
committerJohn McCall <rjmccall@apple.com>
Sun, 13 Feb 2011 00:46:43 +0000 (00:46 +0000)
destruction in the destructor-aliases logic.  Fixes PR 9197.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125447 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Type.h
lib/AST/Type.cpp
lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/destructors.cpp

index 7d7c8b02ec993809e697d20980d927ec25b5f189..8a983fb8a1ec75056d99becfadf0afacaaf16216 100644 (file)
@@ -692,6 +692,19 @@ public:
     return getObjCGCAttr() == Qualifiers::Strong;
   }
 
+  enum DestructionKind {
+    DK_none,
+    DK_cxx_destructor
+  };
+
+  /// isDestructedType - nonzero if objects of this type require
+  /// non-trivial work to clean up after.  Non-zero because it's
+  /// conceivable that qualifiers (objc_gc(weak)?) could make
+  /// something require destruction.
+  DestructionKind isDestructedType() const {
+    return isDestructedTypeImpl(*this);
+  }
+
 private:
   // These methods are implemented in a separate translation unit;
   // "static"-ize them to avoid creating temporary QualTypes in the
@@ -701,6 +714,7 @@ private:
   static SplitQualType getSplitDesugaredType(QualType T);
   static SplitQualType getSplitUnqualifiedTypeImpl(QualType type);
   static QualType IgnoreParens(QualType T);
+  static DestructionKind isDestructedTypeImpl(QualType type);
 };
 
 } // end clang.
index 36d501577c4fd6628a5e07d24900c3c4850b6d46..0130b13b947f72041bf0dc38f24284915eb2290b 100644 (file)
@@ -1576,3 +1576,14 @@ bool Type::hasSizedVLAType() const {
 
   return false;
 }
+
+QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
+  /// Currently, the only destruction kind we recognize is C++ objects
+  /// with non-trivial destructors.
+  const CXXRecordDecl *record =
+    type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+  if (record && !record->hasTrivialDestructor())
+    return DK_cxx_destructor;
+
+  return DK_none;
+}
index d4bd9cbc9ab01c92748072b757b84168b9dfb102..7ffc6e732554bc7f03eb009ad54eddcab956918e 100644 (file)
@@ -60,13 +60,12 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
     return true;
   }
 
-  // If any fields have a non-trivial destructor, we have to emit it
-  // separately.
+  // If any field has a non-trivial destructor, we have to emit the
+  // destructor separately.
   for (CXXRecordDecl::field_iterator I = Class->field_begin(),
          E = Class->field_end(); I != E; ++I)
-    if (const RecordType *RT = (*I)->getType()->getAs<RecordType>())
-      if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor())
-        return true;
+    if ((*I)->getType().isDestructedType())
+      return true;
 
   // Try to find a unique base class with a non-trivial destructor.
   const CXXRecordDecl *UniqueBase = 0;
index 0fc23116a575b40547e5ffa12f490c9b4b786d4e..f382413cba41bd91547e16c824ca963ff6f41f42 100644 (file)
@@ -306,6 +306,26 @@ namespace test6 {
   // CHECK:   invoke void @_ZN5test61BILj0EED2Ev
 }
 
+// PR 9197
+namespace test7 {
+  struct D { ~D(); };
+
+  struct A { ~A(); };
+  A::~A() { }
+
+  struct B : public A {
+    ~B();
+    D arr[1];
+  };
+
+  // Verify that this doesn't get emitted as an alias
+  // CHECK: define void @_ZN5test71BD2Ev(
+  // CHECK:   invoke void @_ZN5test71DD1Ev(
+  // CHECK:   call void @_ZN5test71AD2Ev(
+  B::~B() {}
+
+}
+
 // Checks from test3:
 
   // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr