]> granicus.if.org Git - clang/commitdiff
Perform access control for the implicit calls to base and member destructors
authorJohn McCall <rjmccall@apple.com>
Tue, 16 Mar 2010 21:39:52 +0000 (21:39 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 16 Mar 2010 21:39:52 +0000 (21:39 +0000)
that occur in constructors (on the unwind path).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98681 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/class.access/p4.cpp

index 4c258448daf23976df1ba3b39fed9872b24782af..c6b63673f57abf2a417c4ec49e49a438712cb976 100644 (file)
@@ -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
index dab7d883a1d6e57b9acd0a55811b13f81688f589..776f0ddf1a61e662fa050c566b685e54f7620318 100644 (file)
@@ -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
index c27b0d5013c6700392dcb5209602e7fefdbc7bb5..c0b699a518161d23d75a9a219a451f43d557e20d 100644 (file)
@@ -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.
index 15b336a4d8e6a031edded2ffa813b131f39e1b27..0a7459b50a86a8ef20ec52bbfb48a976182819c3 100644 (file)
@@ -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 {{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;