Look through array types when deciding whether a field requires non-trivial

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
This commit is contained in:
John McCall 2011-02-13 00:46:43 +00:00
Родитель e3c8c64e77
Коммит 0d70d71ccb
4 изменённых файлов: 49 добавлений и 5 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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