]> granicus.if.org Git - clang/commitdiff
Implement DR7
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 6 Jun 2013 23:43:20 +0000 (23:43 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 6 Jun 2013 23:43:20 +0000 (23:43 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
test/CXX/drs/dr0xx.cpp

index c328e71057e90c4c9bee429e176f1c1394a8e90d..40ef1ac75aef9ef102e7ca927c17f3946ae7d328 100644 (file)
@@ -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">,
index 573738cedb9ebeb9187a850f7c92185ac1c2c784..059c3720d67ba427ae52435e070e36f8aca52c79 100644 (file)
@@ -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<CXXRecordDecl>(BaseDecl);
+  CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(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<CXXDestructorDecl*>(Dtor));
     DiagnoseUseOfDecl(Dtor, Location);
index 4298960426dc593db2c09dc98c7388f70fa72950..7ff199d0b1f362820ae42a86dbafd90475714393 100644 (file)
@@ -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}}