]> granicus.if.org Git - clang/commitdiff
Implement access checking for the "delete" operator. Fixes PR9050,
authorDouglas Gregor <dgregor@apple.com>
Tue, 1 Feb 2011 15:50:11 +0000 (15:50 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 1 Feb 2011 15:50:11 +0000 (15:50 +0000)
from Alex Miller!

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprCXX.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
test/CXX/expr/expr.unary/expr.delete/p5.cpp
test/SemaCXX/new-delete.cpp

index 3e7f48cf8141995b6455eb236123c8764977c134..316db752153d37f247b970d1eef5f6239fa03cb6 100644 (file)
@@ -564,6 +564,9 @@ def err_access_field: Error<
 def err_access_ctor_field :
     Error<"field of type %1 has %select{private|protected}2 constructor">,
     AccessControl;
+def err_access_dtor : Error<
+  "calling a %select{private|protected}1 destructor of class %0">, 
+  AccessControl;
 def err_access_dtor_base :
     Error<"base class %0 has %select{private|protected}1 destructor">,
     AccessControl;
index 82e818fba0528868ec2499c072f999373d1a1bf8..7bc9af1191e66a192d571c8d5360d7c8cc6bc01c 100644 (file)
@@ -1687,7 +1687,15 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
 
     MarkDeclarationReferenced(StartLoc, OperatorDelete);
     
-    // FIXME: Check access and ambiguity of operator delete and destructor.
+    // Check access and ambiguity of operator delete and destructor.
+    if (const RecordType *RT = PointeeElem->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) {
+          CheckDestructorAccess(Ex->getExprLoc(), Dtor, 
+                      PDiag(diag::err_access_dtor) << PointeeElem);
+      }
+    }
+
   }
 
   return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
index bb1d67f51a6c246a90cd3c987563c7e88b306212..634369dd52304028ab36f3e8aef4486e346f9441 100644 (file)
@@ -89,6 +89,7 @@ namespace test2 {
 
 namespace test3 {
   class A {
+  public:
     ~A();
   };
 
index 2fa30e59dca54e7685433e7ded4e440a5e3246c5..ecb29189af60b151df6792c38e3dc6caa448a259 100644 (file)
@@ -24,11 +24,23 @@ void f0(T2_A *a) { T2_C x; x.f0(a); }
 class T2_A { };
 
 // An alternate version of the same.
-//
-// FIXME: Revisit this case when we have access control.
 class T3_A;
 template<typename T>
-struct T3_B { void f0(T *a) { delete a; } };
-struct T3_C { T3_B<T3_A> x; void f0(T3_A *a) { x.f0(a); } };
+struct T3_B { 
+  void f0(T *a) { 
+    delete a; // expected-error{{calling a private destructor of class 'T3_A'}}
+  } 
+};
+
+struct T3_C { 
+  T3_B<T3_A> x; 
+  void f0(T3_A *a) { 
+    x.f0(a); // expected-note{{in instantiation of member function 'T3_B<T3_A>::f0' requested here}}
+  } 
+};
+
 void f0(T3_A *a) { T3_C x; x.f0(a); }
-class T3_A { private: ~T3_A(); };
+class T3_A { 
+private: 
+  ~T3_A(); // expected-note{{declared private here}}
+};
index 19d5df6673ef847de2efbb2b31ea705f0f148f62..13ef461e7c0d8b20ce8478eac5940060f03c50f3 100644 (file)
@@ -234,6 +234,17 @@ void f(X14 *x14a, X14 *x14b) {
   delete x14a;
 }
 
+class X15 {
+private:
+  X15(); // expected-note {{declared private here}}
+  ~X15(); // expected-note {{declared private here}}
+};
+
+void f(X15* x) {
+  new X15(); // expected-error {{calling a private constructor}}
+  delete x; // expected-error {{calling a private destructor}}
+}
+
 namespace PR5918 { // Look for template operator new overloads.
   struct S { template<typename T> static void* operator new(size_t, T); };
   void test() {