[Bug libstdc++/54351] New: ~unique_ptr() should not set __p to null

2012-08-22 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54351

 Bug #: 54351
   Summary: ~unique_ptr() should not set __p to null
Classification: Unclassified
   Product: gcc
   Version: 4.7.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: gro...@google.com


libstdc++'s unique_ptr destructor is currently implemented as:

~unique_ptr() noexcept { reset(); }

This has the effect of resetting the stored pointer to null, and then invoking
the deleter on the formerly-stored pointer. I believe this is inconsistent with
the language standard, which specifies the destructor as "If get() == nullptr
there are no effects. Otherwise get_deleter()(get())." (note no mention of any
side effects on the value of the stored pointer). This is a problem because
this implementation will break code that (legitimately, AFAICT) relies on being
able to continue to invoke operations on the scoped_ptr while the destructor is
executing.

The fix is to reimplement the destructor (in both the base template and the
array specialization) as

~unique_ptr() noexcept {
 if (__p != pointer())
   get_deleter()(__p);
}

If the intent is to zero out __p to help catch use-after-destruction errors, I
believe it would be permissible to set __p to null after the call to
get_deleter(), because at that point the change would no longer be visible to
conforming code.

To make this concrete, here's an example: the following program prints "bad"
under libstdc++, but I believe a standard-conforming implementation is required
to print "good":

=
#include 
#include 

using std::cout;
using std::endl;
using std::unique_ptr;

struct A;

struct B {
 unique_ptr a;
};

struct A {
 B* b;
 ~A() {
   if (b->a == nullptr) {
 cout << "bad" << endl;
   } else {
 cout << "good" << endl;
   }
 }
};

int main(int argc, char** argv) {
 B b;
 b.a.reset(new A);
 b.a->b = &b;
}
===

As a point of comparison, MSVC++ 2010 prints "good" on this example program.


[Bug libstdc++/54351] ~unique_ptr() should not set __p to null

2012-08-22 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54351

--- Comment #5 from Geoff Romer  2012-08-22 19:11:17 
UTC ---
Don't forget the array specialization.

Doesn't the first line of your new destructor shadow the __p member with a __p
local variable? Why is that line needed at all?


[Bug libstdc++/54351] ~unique_ptr() should not set stored pointer to null

2012-08-22 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54351

--- Comment #7 from Geoff Romer  2012-08-22 19:49:28 
UTC ---
(In reply to comment #6)
> (In reply to comment #5)
> > Don't forget the array specialization.
> 
> I won't :-)
> 
> > Doesn't the first line of your new destructor shadow the __p member with a 
> > __p
> > local variable? Why is that line needed at all?
> 
> There is no __p member.

Ah, sorry, I was evidently misreading something. I've corrected the bug
description.


[Bug libstdc++/58159] New: unique_ptr::reset should have debug assertion for "self-reset"

2013-08-14 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58159

Bug ID: 58159
   Summary: unique_ptr::reset should have debug assertion for
"self-reset"
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gromer at google dot com

unique_ptr::reset() should have a debug assertion for the case that the input
pointer is not null, and is equal to the pointer already stored. This is
virtually always an error: it violates the basic ownership logic of unique_ptr,
and leaves unique_ptr holding a dangling pointer. Strictly speaking, this is
not undefined behavior in itself, but almost any subsequent operation other
than release() (even destroying the unique_ptr) will produce undefined
behavior, so this seems like a highly defensible condition to assert on, at
least in debug mode.

This kind of error is rare, but it does happen; see e.g.
https://code.google.com/p/chromium/issues/detail?id=162971.


[Bug libstdc++/58159] unique_ptr::reset should have debug assertion for "self-reset"

2013-08-14 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58159

Geoff Romer  changed:

   What|Removed |Added

 CC||gromer at google dot com
   Severity|normal  |enhancement


[Bug libstdc++/58159] unique_ptr::reset should have debug assertion for "self-reset"

2013-08-14 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58159

--- Comment #3 from Geoff Romer  ---
What's the standard of review here? If we can only assert on undefined
behavior, even in debug mode, then this just can't be done (although maybe we
should make this undefined in the Standard). If we can assert on behavior
that's technically well-defined, but very likely to lead to undefined behavior,
and very far from accepted usage norms, then I think this is OK (even for
custom deleters). The kinds of uses you're concerned about (e.g. using
p.reset(p.get()) to invoke some operation on *p) seem really marginal to me.


[Bug preprocessor/20262] __LINE__ implementation flaky.

2013-12-16 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20262

Geoff Romer  changed:

   What|Removed |Added

 CC||gromer at google dot com

--- Comment #5 from Geoff Romer  ---
The issue isn't the flexibility in "presumed", it's the flexibility in "source
line": the standard defines line number in terms of the "current token", but
gives no explicit guidance about which token is considered "current" in a case
like this, where the preprocessor is arguably expanding two different macros at
the same time.


[Bug libstdc++/54351] ~unique_ptr() should not set stored pointer to null

2012-12-18 Thread gromer at google dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54351



--- Comment #11 from Geoff Romer  2012-12-18 21:59:23 
UTC ---

>From discussion on the C++ LWG reflector, it appears that the standard's

requirements on library types are intended to apply only during their lifetime,

although the standard does not currently make this clear. LWG 2224

(http://cplusplus.github.com/LWG/lwg-active.html#2224) is tracking this issue,

and its resolution should give a definitive answer.



That being the case, the old behavior was not a bug, but conformant with the

the intent of the standard (if not the precise wording). The new behavior is

conformant as well, of course, so it's up to you whether to revert the changes;

I just wanted to document for future reference that ~unique_ptr is in fact

permitted to modify the stored pointer before invoking the deleter, so this bug

report should not be an obstacle to e.g. having ~unique_ptr store a poison

value in order to catch client bugs.


[Bug libstdc++/60970] New: Support std::hash with enum types (LWG 2148)

2014-04-25 Thread gromer at google dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970

Bug ID: 60970
   Summary: Support std::hash with enum types (LWG 2148)
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gromer at google dot com

std::hash appears to be undefined when T is an enum type, contrary to the
resolution of LWG 2148
(http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2148).


[Bug libstdc++/38265] STL treats explicit constructors as converting constructors

2015-05-19 Thread gromer at google dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38265

Geoff Romer  changed:

   What|Removed |Added

 CC||gromer at google dot com

--- Comment #14 from Geoff Romer  ---
> The C++11 standard clarifies that this is intended to work. The range
> constructors require the type to be EmplaceConstructible into the container
> from the iterator's value_type

But see [sequence.reqmts]/p3: "i and j denote iterators satisfying input
iterator requirements and refer to elements implicitly convertible to
value_type". So this is not "intended to work" per se; a conforming library
could disallow it. However, the notes on LWG 536 say "Some support, not
universal, for respecting the explicit qualifier", so it looks like the
standard intentionally permits this as a conforming extension.

In principle, I think "perfect initialization" is what's called for here: the
range ctor should be explicit if and only if it uses an explicit constructor
for value_type. However, I doubt it's worth the trouble (OTOH, it definitely
will be worth the trouble when/if we get single-argument range constructors).


[Bug libstdc++/58159] unique_ptr::reset should have debug assertion for "self-reset"

2014-09-17 Thread gromer at google dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58159

--- Comment #6 from Geoff Romer  ---
A Chromium maintainer privately pointed out a use case that would be thwarted
by a check like this: basically, unique_ptr is used to hold pointers from a
legacy API, using a custom deleter that decrements a reference count rather
than actually destroying the object. If the legacy API returns the same pointer
from multiple calls, this can lead to reset() being legitimately called with a
pointer equal to the stored value.

So on reflection, I agree this can only be done for default_delete.