]> granicus.if.org Git - clang/commitdiff
[ms-cxxabi] Elide dtor access checks for pass-by-val objects in callees
authorHans Wennborg <hans@hanshq.net>
Mon, 13 Jan 2014 17:23:24 +0000 (17:23 +0000)
committerHans Wennborg <hans@hanshq.net>
Mon, 13 Jan 2014 17:23:24 +0000 (17:23 +0000)
The ABI requires the destructor to be invoked in the callee, but the
standard does not require access checks here so we avoid doing direct
access checks on the destructor.

If we end up needing to define an implicit destructor, we don't skip
access checks for the base class, etc. Those checks are effectively part
of generating the destructor definition, and aren't affected by which TU
the check is performed in.

Differential Revision: http://llvm-reviews.chandlerc.com/D2409

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

lib/Sema/SemaChecking.cpp
test/SemaCXX/microsoft-dtor-lookup.cpp
test/SemaObjCXX/microsoft-abi-byval.mm

index 82b3da6c2e1a0039b703ee5680132a506896db11..0e2b1f64d600a58a9f3516f60bb30b1b9d65e720 100644 (file)
@@ -6241,12 +6241,21 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
 
     // MSVC destroys objects passed by value in the callee.  Therefore a
     // function definition which takes such a parameter must be able to call the
-    // object's destructor.
+    // object's destructor.  However, we don't perform any direct access check
+    // on the dtor.
     if (getLangOpts().CPlusPlus && Context.getTargetInfo()
                                        .getCXXABI()
                                        .areArgsDestroyedLeftToRightInCallee()) {
-      if (const RecordType *RT = Param->getType()->getAs<RecordType>())
-        FinalizeVarWithDestructor(Param, RT);
+      if (const RecordType *RT = Param->getType()->getAs<RecordType>()) {
+        CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+        if (!ClassDecl->isInvalidDecl() &&
+            !ClassDecl->hasIrrelevantDestructor() &&
+            !ClassDecl->isDependentContext()) {
+          CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+          MarkFunctionReferenced(Param->getLocation(), Destructor);
+          DiagnoseUseOfDecl(Destructor, Param->getLocation());
+        }
+      }
     }
   }
 
index d264bab09bf74249022915e137ef822f5fd71f0a..a25ede6d6e85d6fb72379533b608d3eb92312506 100644 (file)
@@ -32,10 +32,9 @@ namespace Test2 {
 // requires a dtor for B, but we can't implicitly define it because ~A is
 // private.  bar should be able to call A's private dtor without error, even
 // though MSVC rejects bar.
-
 class A {
 private:
-  ~A(); // expected-note 2{{declared private here}}
+  ~A(); // expected-note {{declared private here}}
   int a;
 };
 
@@ -54,7 +53,7 @@ struct D {
 };
 
 void foo(B b) { } // expected-note {{implicit destructor for 'Test2::B' first required here}}
-void bar(A a) { } // expected-error {{variable of type 'Test2::A' has private destructor}}
+void bar(A a) { } // no error; MSVC rejects this, but we skip the direct access check.
 void baz(D d) { } // no error
 
 }
@@ -64,13 +63,13 @@ namespace Test3 {
 
 class A {
   A();
-  ~A(); // expected-note 2{{implicitly declared private here}}
+  ~A(); // expected-note {{implicitly declared private here}}
   friend void bar(A);
   int a;
 };
 
 void bar(A a) { }
-void baz(A a) { } // expected-error {{variable of type 'Test3::A' has private destructor}}
+void baz(A a) { } // no error; MSVC rejects this, but the standard allows it.
 
 // MSVC accepts foo() but we reject it for consistency with Itanium.  MSVC also
 // rejects this if A has a copy ctor or if we call A's ctor.
index f0c4caa9e06d891f16d49ce47aebfa27477ff9ef..9b3a5c9e05772514260d512ee3f6a661b86767fb 100644 (file)
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -cxx-abi microsoft -Wno-objc-root-class %s
+// expected-no-diagnostics
 
 class Foo {
-  ~Foo(); // expected-note {{implicitly declared private here}}
+  ~Foo();
 };
 
 @interface bar
@@ -9,6 +10,6 @@ class Foo {
 @end
 
 @implementation bar
-- (void) my_method: (Foo)arg { // expected-error {{variable of type 'Foo' has private destructor}}
+- (void) my_method: (Foo)arg { // no error; MS ABI will call Foo's dtor, but we skip the access check.
 }
 @end