Bug 54812 - [C++11] Delete expression doesn't respect access of defaulted destructor
Summary: [C++11] Delete expression doesn't respect access of defaulted destructor
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 4.9.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 56429 57595 61087 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-10-04 14:37 UTC by Daniel Krügler
Modified: 2016-02-03 23:29 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-10-05 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Krügler 2012-10-04 14:37:11 UTC
While working on a further simplification of the is_constructible traits using gcc 4.8.0 20120930 (experimental) with the compiler flags

-Wall -pedantic -std=c++11

the following program demonstrates that private access of a *defaulted* destructor is not properly respected during delete expressions:

//--------------------
#include <new>

template<class T>
T&& declval();

struct P1 {
private:
  ~P1();
};

struct P2 {
  ~P2() = delete;
};

struct P3 {
private:
  ~P3() = default;
};

typedef decltype(::delete declval<P1*>()) t1;  // #20
typedef decltype(::delete declval<P2*>()) t2;  // #21
typedef decltype(::delete declval<P3*>()) t3;  // #22 *Not* detected
//--------------------

This program produces only two errors instead of the expected three:

"main.cpp|8|error: 'P1::~P1()' is private|
 main.cpp|20|error: within this context|
 main.cpp|21|error: use of deleted function 'P2::~P2()'|
 main.cpp|12|error: declared here|
"

According to [expr.delete] p10 access control shall be done for the destructor.
Comment 1 Paolo Carlini 2012-10-05 20:53:35 UTC
Uhm, this is not trivial to fix. The difference between P1 and P3 is that for the former from build_delete we call build_dtor_call which eventually also calls the required perform_or_defer_access_check, whereas for the latter the function just notices that TYPE_HAS_TRIVIAL_DESTRUCTOR and early returns (via build_op_delete_call). Arguably, a TYPE_HAS_TRIVIAL_DESTRUCTOR true for a destructor which actually is private and can't be called sounds a bit strange but for sure the choice makes sense wrt the rest of the front-end and the standard... I'll double check soon a few things.

Anyway, here, I only wanted to ask you if this is a show-stopper for your work, because I don't know how much time it will take.
Comment 2 Daniel Krügler 2012-10-05 21:00:31 UTC
(In reply to comment #1)
> Anyway, here, I only wanted to ask you if this is a show-stopper for your work,
> because I don't know how much time it will take.

While I think that this should be fixed, it will only prevent that I would directly convert is_constructible to use the combined 

::delete ::new ((void*) nullptr) T(args) 

expression. Our current implementation is not sensitive to this problem, because we use is_destructible within. I noticed that there are still a bunches of opportunities to simplify is_constructible (and friends) because a lot of previous compiler defects have been fixed. So, really no need to hurry!
Comment 3 Paolo Carlini 2012-10-05 21:08:04 UTC
Of course it should be fixed, it *must* be fixed, actually! And it's really annoying that this bug affecting private defaulted destructors (which, I bet, aren't that common for most programs not using SFINAE tricks!?!) is preventing us from deploying right now the very elegant ::delete ::new pattern which otherwise finally works pretty well. What can I add? Do your best, and thanks again!
Comment 4 Paolo Carlini 2012-10-05 21:10:25 UTC
Let's ask Jason right now, if he can see a smart way to do access control on defaulted destructors...
Comment 5 Paolo Carlini 2012-10-05 23:25:47 UTC
By the way, this compiles:

struct P3 {
private:
  ~P3() = default;
};

P3 p3;

thus there is little hope that we get an error for #22 ..
Comment 6 Daniel Krügler 2012-10-06 08:11:48 UTC
(In reply to comment #5)
I double-checked whether this might be related to

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1507

from a different perspective, but I'm pretty sure it isn't. 12.4 p11 seems very clear that the destructor would be called implicitly here and that access checking happens.
Comment 7 Jason Merrill 2013-05-30 20:40:09 UTC
Various places in the compiler need to be updated to not assume that trivial implies callable.
Comment 8 Jonathan Wakely 2013-06-12 11:32:20 UTC
*** Bug 57595 has been marked as a duplicate of this bug. ***
Comment 9 Jonathan Wakely 2013-07-26 12:34:37 UTC
*** Bug 56429 has been marked as a duplicate of this bug. ***
Comment 10 Jonathan Wakely 2013-07-26 12:35:41 UTC
(In reply to Paolo Carlini from comment #3)
> Of course it should be fixed, it *must* be fixed, actually! And it's really
> annoying that this bug affecting private defaulted destructors (which, I
> bet, aren't that common for most programs not using SFINAE tricks!?!)

The bug affects protected destructors too, and they're commonly used for base classes to prevent deletion via pointer-to-base.  This bug means you can't make them trivial by defining them as defaulted.

The problem isn't confined to delete expressions as the example from PR56429 shows:

class A
{
    A() = default;
};
struct B : A { };

B b;
Comment 11 Paolo Carlini 2013-07-26 12:38:06 UTC
Jason call if we want this to be a P2. Well, maybe some wrong code bugs I recently bumped to P2 should be P1 ;)
Comment 12 Paolo Carlini 2013-10-23 18:51:07 UTC
Thus this is fixed in r203985.
Comment 13 paolo@gcc.gnu.org 2013-10-25 10:54:59 UTC
Author: paolo
Date: Fri Oct 25 10:54:56 2013
New Revision: 204057

URL: http://gcc.gnu.org/viewcvs?rev=204057&root=gcc&view=rev
Log:
2013-10-25  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54812
	* g++.dg/cpp0x/defaulted47.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/defaulted47.C
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 14 Jonathan Wakely 2014-05-06 21:56:54 UTC
*** Bug 61087 has been marked as a duplicate of this bug. ***
Comment 15 Che Amaya 2016-02-03 23:29:10 UTC Comment hidden (spam)