Perform access control even for the implicit destructor calls from implicit

destructor definitions.  Remove some code duplication.

llvm-svn: 98611
This commit is contained in:
John McCall 2010-03-16 05:36:30 +00:00
parent 5125770346
commit f857e0bbe7
3 changed files with 14 additions and 42 deletions

View File

@ -3819,45 +3819,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
DeclContext *PreviousContext = CurContext;
CurContext = Destructor;
// C++ [class.dtor] p5
// Before the implicitly-declared default destructor for a class is
// implicitly defined, all the implicitly-declared default destructors
// for its base class and its non-static data members shall have been
// implicitly defined.
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
E = ClassDecl->bases_end(); Base != E; ++Base) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (!BaseClassDecl->hasTrivialDestructor()) {
if (CXXDestructorDecl *BaseDtor =
const_cast<CXXDestructorDecl*>(BaseClassDecl->getDestructor(Context)))
MarkDeclarationReferenced(CurrentLocation, BaseDtor);
else
assert(false &&
"DefineImplicitDestructor - missing dtor in a base class");
}
}
MarkBaseAndMemberDestructorsReferenced(Destructor);
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
E = ClassDecl->field_end(); Field != E; ++Field) {
QualType FieldType = Context.getCanonicalType((*Field)->getType());
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
if (!FieldClassDecl->hasTrivialDestructor()) {
if (CXXDestructorDecl *FieldDtor =
const_cast<CXXDestructorDecl*>(
FieldClassDecl->getDestructor(Context)))
MarkDeclarationReferenced(CurrentLocation, FieldDtor);
else
assert(false &&
"DefineImplicitDestructor - missing dtor in class of a data member");
}
}
}
// FIXME: If CheckDestructor fails, we should emit a note about where the
// implicit destructor was needed.
if (CheckDestructor(Destructor)) {

View File

@ -112,8 +112,8 @@ namespace test3 {
A local; // expected-error {{variable of type 'test3::A' has private destructor}}
}
template <unsigned N> class Base { ~Base(); }; // expected-note 4 {{declared private here}}
class Base2 : virtual Base<2> { ~Base2(); }; // expected-note {{declared private here}}
template <unsigned N> class Base { ~Base(); }; // expected-note 8 {{declared private here}}
class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 2 {{declared private here}}
class Base3 : virtual Base<3> { public: ~Base3(); };
// These don't cause diagnostics because we don't need the destructor.
@ -129,6 +129,15 @@ namespace test3 {
{
~Derived2() {}
};
class Derived3 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}} \
// expected-error {{inherited virtual base class 'Base<3>' has private destructor}}
Base<0>, // expected-error {{base class 'Base<0>' has private destructor}}
virtual Base<1>, // expected-error {{base class 'Base<1>' has private destructor}}
Base2, // expected-error {{base class 'test3::Base2' has private destructor}}
virtual Base3
{};
Derived3 d3;
}
// Conversion functions.

View File

@ -36,10 +36,10 @@ struct Base {
template<typename T>
struct Derived : Base<T> {
virtual void foo() { } // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}}
virtual void foo() { }
};
template struct Derived<int>;
template struct Derived<int>; // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}}
template<typename T>
struct HasOutOfLineKey {