diff options
-rw-r--r-- | lib/Sema/Sema.h | 9 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 48 | ||||
-rw-r--r-- | test/CXX/class.access/p4.cpp | 17 |
4 files changed, 31 insertions, 46 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 4c258448da..c6b63673f5 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2473,10 +2473,11 @@ public: bool IsImplicitConstructor, bool AnyErrors); - /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl, - /// mark all its non-trivial member and base destructor declarations - /// as referenced. - void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor); + /// MarkBaseAndMemberDestructorsReferenced - Given a record decl, + /// mark all the non-trivial destructors of its members and bases as + /// referenced. + void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc, + CXXRecordDecl *Record); /// ClassesWithUnmarkedVirtualMembers - Contains record decls whose virtual /// members need to be marked as referenced at the end of the translation diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dab7d883a1..776f0ddf1a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4281,7 +4281,8 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, DiagnoseInvalidJumps(Body); if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) - MarkBaseAndMemberDestructorsReferenced(Destructor); + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), + Destructor->getParent()); // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c27b0d5013..c0b699a518 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1643,29 +1643,14 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, Constructor->setNumBaseOrMemberInitializers(NumInitializers); CXXBaseOrMemberInitializer **baseOrMemberInitializers = new (Context) CXXBaseOrMemberInitializer*[NumInitializers]; - + memcpy(baseOrMemberInitializers, AllToInit.data(), + NumInitializers * sizeof(CXXBaseOrMemberInitializer*)); Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers); - for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) { - CXXBaseOrMemberInitializer *Member = AllToInit[Idx]; - baseOrMemberInitializers[Idx] = Member; - if (!Member->isBaseInitializer()) - continue; - const Type *BaseType = Member->getBaseClass(); - const RecordType *RT = BaseType->getAs<RecordType>(); - if (!RT) - continue; - CXXRecordDecl *BaseClassDecl = - cast<CXXRecordDecl>(RT->getDecl()); - - // We don't know if a dependent type will have an implicit destructor. - if (BaseClassDecl->isDependentType()) - continue; - if (BaseClassDecl->hasTrivialDestructor()) - continue; - CXXDestructorDecl *DD = BaseClassDecl->getDestructor(Context); - MarkDeclarationReferenced(Constructor->getLocation(), DD); - } + // Constructors implicitly reference the base and member + // destructors. + MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(), + Constructor->getParent()); } return HadError; @@ -1848,9 +1833,10 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, } void -Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { - // Ignore dependent destructors. - if (Destructor->isDependentContext()) +Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, + CXXRecordDecl *ClassDecl) { + // Ignore dependent contexts. + if (ClassDecl->isDependentContext()) return; // FIXME: all the access-control diagnostics are positioned on the @@ -1858,8 +1844,6 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { // user might reasonably want to know why the destructor is being // emitted, and we currently don't say. - CXXRecordDecl *ClassDecl = Destructor->getParent(); - // Non-static data members. for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), E = ClassDecl->field_end(); I != E; ++I) { @@ -1881,8 +1865,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { << Field->getDeclName() << FieldType); - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); + MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); } llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; @@ -1910,8 +1893,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { << Base->getType() << Base->getSourceRange()); - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); + MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); } // Virtual bases. @@ -1935,8 +1917,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { PartialDiagnostic(diag::err_access_dtor_vbase) << VBase->getType()); - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); + MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); } } @@ -3819,7 +3800,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, DeclContext *PreviousContext = CurContext; CurContext = Destructor; - MarkBaseAndMemberDestructorsReferenced(Destructor); + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), + Destructor->getParent()); // FIXME: If CheckDestructor fails, we should emit a note about where the // implicit destructor was needed. diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index 15b336a4d8..0a7459b50a 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -112,9 +112,10 @@ namespace test3 { A local; // expected-error {{variable of type 'test3::A' has private destructor}} } - 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(); }; + template <unsigned N> class Base { ~Base(); }; // expected-note 14 {{declared private here}} + class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 3 {{declared private here}} \ + // expected-error {{base class 'Base<2>' has private destructor}} + class Base3 : virtual Base<3> { public: ~Base3(); }; // expected-error {{base class 'Base<3>' has private destructor}} // These don't cause diagnostics because we don't need the destructor. class Derived0 : Base<0> { ~Derived0(); }; @@ -130,11 +131,11 @@ 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}} + class Derived3 : // expected-error 2 {{inherited virtual base class 'Base<2>' has private destructor}} \ + // expected-error 2 {{inherited virtual base class 'Base<3>' has private destructor}} + Base<0>, // expected-error 2 {{base class 'Base<0>' has private destructor}} + virtual Base<1>, // expected-error 2 {{base class 'Base<1>' has private destructor}} + Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}} virtual Base3 {}; Derived3 d3; |