зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
e3c8c64e77
Коммит
0d70d71ccb
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче