From: David Majnemer Date: Thu, 6 Jun 2013 23:43:20 +0000 (+0000) Subject: Implement DR7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=585bee48bac063f31696e308798f9432b5ba4116;p=clang Implement DR7 Disallowing deriving from classes that have private virtual base classes except in instances where the deriving class would be able to cast itself to the private virtual base via a different derivation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183462 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c328e71057..40ef1ac75a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1011,8 +1011,8 @@ def err_access_dtor_base : Error<"base class %0 has %select{private|protected}1 destructor">, AccessControl; def err_access_dtor_vbase : - Error<"inherited virtual base class %0 has " - "%select{private|protected}1 destructor">, + Error<"inherited virtual base class %1 has " + "%select{private|protected}2 destructor">, AccessControl; def err_access_dtor_temp : Error<"temporary of type %0 has %select{private|protected}1 destructor">, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 573738cedb..059c3720d6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1311,7 +1311,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, assert(BaseDecl && "Record type has no declaration"); BaseDecl = BaseDecl->getDefinition(); assert(BaseDecl && "Base type is not incomplete, but has no definition"); - CXXRecordDecl * CXXBaseDecl = cast(BaseDecl); + CXXRecordDecl *CXXBaseDecl = cast(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); // C++ [class]p3: @@ -3806,10 +3806,17 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); - CheckDestructorAccess(ClassDecl->getLocation(), Dtor, - PDiag(diag::err_access_dtor_vbase) - << VBase->getType(), - Context.getTypeDeclType(ClassDecl)); + if (CheckDestructorAccess( + ClassDecl->getLocation(), Dtor, + PDiag(diag::err_access_dtor_vbase) + << Context.getTypeDeclType(ClassDecl) << VBase->getType(), + Context.getTypeDeclType(ClassDecl)) == + AR_accessible) { + CheckDerivedToBaseConversion( + Context.getTypeDeclType(ClassDecl), VBase->getType(), + diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(), + SourceRange(), DeclarationName(), 0); + } MarkFunctionReferenced(Location, const_cast(Dtor)); DiagnoseUseOfDecl(Dtor, Location); diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index 4298960426..7ff199d0b1 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -59,10 +59,13 @@ namespace dr5 { // dr5: yes const C c = e; } -namespace dr7 { // dr7: no +namespace dr7 { // dr7: yes class A { public: ~A(); }; - class B : virtual private A {}; - class C : public B {} c; // FIXME: should be rejected, ~A is inaccessible + class B : virtual private A {}; // expected-note 2 {{declared private here}} + class C : public B {} c; // expected-error 2 {{inherited virtual base class 'dr7::A' has private destructor}} \ + // expected-note {{implicit default constructor for 'dr7::C' first required here}} \ + // expected-note {{implicit default destructor for 'dr7::C' first required here}} + class VeryDerivedC : public B, virtual public A {} vdc; class X { ~X(); }; // expected-note {{here}} class Y : X { ~Y() {} }; // expected-error {{private destructor}}