Re: [PATCH] assert that deleting by pointer to base in unique_ptr does not cause UB
On Wed, 22 Sept 2021 at 18:56, Antony Polukhin wrote: > > ср, 22 сент. 2021 г. в 20:44, Jonathan Wakely : > > > > On Wed, 22 Sept 2021 at 18:09, Antony Polukhin wrote: > > > > > > std::unique_ptr allows construction from std::unique_ptr of derived > > > type as per [unique.ptr.single.asgn] and [unique.ptr.single.ctor]. If > > > std::default_delete is used with std::unique_ptr, then after such > > > construction a delete is called on a pointer to base. According to > > > [expr.delete] calling a delete on a non similar object without a > > > virtual destructor is an undefined behavior. > > > > > > This patch turns that undefined behavior into static assertions inside > > > std::unique_ptr. > > > > The undefined behaviour only happens if the destructor is actually > > reached at runtime, but won't these static assertions make it > > ill-formed to instantiate these members, even if the UB never happens? > > > > For example, if you ensure that release() is called before > > destruction, the undefined delete never happens. > > Ugh... I've missed that use case. Patch is just wrong, discard it It's a horrible (and probably unrealistic) use case, but we're required to accept it. I should a test case to the testsuite, just to make sure we continue to accept it without errors.
Re: [PATCH] assert that deleting by pointer to base in unique_ptr does not cause UB
ср, 22 сент. 2021 г. в 20:44, Jonathan Wakely : > > On Wed, 22 Sept 2021 at 18:09, Antony Polukhin wrote: > > > > std::unique_ptr allows construction from std::unique_ptr of derived > > type as per [unique.ptr.single.asgn] and [unique.ptr.single.ctor]. If > > std::default_delete is used with std::unique_ptr, then after such > > construction a delete is called on a pointer to base. According to > > [expr.delete] calling a delete on a non similar object without a > > virtual destructor is an undefined behavior. > > > > This patch turns that undefined behavior into static assertions inside > > std::unique_ptr. > > The undefined behaviour only happens if the destructor is actually > reached at runtime, but won't these static assertions make it > ill-formed to instantiate these members, even if the UB never happens? > > For example, if you ensure that release() is called before > destruction, the undefined delete never happens. Ugh... I've missed that use case. Patch is just wrong, discard it -- Best regards, Antony Polukhin
Re: [PATCH] assert that deleting by pointer to base in unique_ptr does not cause UB
On Wed, 22 Sept 2021 at 20:49, Antony Polukhin wrote: > > ср, 22 сент. 2021 г. в 20:23, Ville Voutilainen : > > > > On Wed, 22 Sept 2021 at 20:09, Antony Polukhin via Libstdc++ > > wrote: > > > > > > std::unique_ptr allows construction from std::unique_ptr of derived > > > type as per [unique.ptr.single.asgn] and [unique.ptr.single.ctor]. If > > > std::default_delete is used with std::unique_ptr, then after such > > > construction a delete is called on a pointer to base. According to > > > [expr.delete] calling a delete on a non similar object without a > > > virtual destructor is an undefined behavior. > > > > > > This patch turns that undefined behavior into static assertions inside > > > std::unique_ptr. > > > > I don't understand the sizeof(_Tp) == sizeof(_Up) part in the > > static_assert. I fail to see how > > a same-size check suggests that the types are similar enough that a > > delete-expression works. > > I used the following logic: > [unique.ptr.single.*] sections have the constraint that > "unique_ptr::pointer is implicitly convertible to pointer". > There's already a static assert that T in unique_ptr is not void, > so U either has to be the same type T, or a type derived from T. If a > derived type adds members, then size changes and types are not similar > as the decompositions won't have the qualification-decompositions with > the same n. Right, but the delete-expression on a non-polymorphic type where the static type and the dynamic type are different is UB regardless of whether the derived type adds members.
Re: [PATCH] assert that deleting by pointer to base in unique_ptr does not cause UB
ср, 22 сент. 2021 г. в 20:23, Ville Voutilainen : > > On Wed, 22 Sept 2021 at 20:09, Antony Polukhin via Libstdc++ > wrote: > > > > std::unique_ptr allows construction from std::unique_ptr of derived > > type as per [unique.ptr.single.asgn] and [unique.ptr.single.ctor]. If > > std::default_delete is used with std::unique_ptr, then after such > > construction a delete is called on a pointer to base. According to > > [expr.delete] calling a delete on a non similar object without a > > virtual destructor is an undefined behavior. > > > > This patch turns that undefined behavior into static assertions inside > > std::unique_ptr. > > I don't understand the sizeof(_Tp) == sizeof(_Up) part in the > static_assert. I fail to see how > a same-size check suggests that the types are similar enough that a > delete-expression works. I used the following logic: [unique.ptr.single.*] sections have the constraint that "unique_ptr::pointer is implicitly convertible to pointer". There's already a static assert that T in unique_ptr is not void, so U either has to be the same type T, or a type derived from T. If a derived type adds members, then size changes and types are not similar as the decompositions won't have the qualification-decompositions with the same n. -- Best regards, Antony Polukhin
Re: [PATCH] assert that deleting by pointer to base in unique_ptr does not cause UB
On Wed, 22 Sept 2021 at 18:09, Antony Polukhin wrote: > > std::unique_ptr allows construction from std::unique_ptr of derived > type as per [unique.ptr.single.asgn] and [unique.ptr.single.ctor]. If > std::default_delete is used with std::unique_ptr, then after such > construction a delete is called on a pointer to base. According to > [expr.delete] calling a delete on a non similar object without a > virtual destructor is an undefined behavior. > > This patch turns that undefined behavior into static assertions inside > std::unique_ptr. The undefined behaviour only happens if the destructor is actually reached at runtime, but won't these static assertions make it ill-formed to instantiate these members, even if the UB never happens? For example, if you ensure that release() is called before destruction, the undefined delete never happens.
Re: [PATCH] assert that deleting by pointer to base in unique_ptr does not cause UB
On Wed, 22 Sept 2021 at 20:09, Antony Polukhin via Libstdc++ wrote: > > std::unique_ptr allows construction from std::unique_ptr of derived > type as per [unique.ptr.single.asgn] and [unique.ptr.single.ctor]. If > std::default_delete is used with std::unique_ptr, then after such > construction a delete is called on a pointer to base. According to > [expr.delete] calling a delete on a non similar object without a > virtual destructor is an undefined behavior. > > This patch turns that undefined behavior into static assertions inside > std::unique_ptr. I don't understand the sizeof(_Tp) == sizeof(_Up) part in the static_assert. I fail to see how a same-size check suggests that the types are similar enough that a delete-expression works.