This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C++ PATCH] P0784R7 constexpr new fixes (PR c++/91369)


On 30/10/19 23:05 +0100, Jakub Jelinek wrote:
On Wed, Oct 30, 2019 at 04:26:17PM -0400, Jason Merrill wrote:
OK.

Thanks, committed.

> Now, for the accepts invalid issues.
>  From what I understood, in constant evaluation
> ::operator new{,[]} or ::operator delete{,[]}
> can't be called from anywhere, only from new/delete expressions or
> std::allocator<T>::{,de}allocate, is that correct?
> If so, perhaps we need some CALL_EXPR flag that we'd set on the call
> coming from new/delete expressions and disallow calls to
> replaceable global allocator functions in constexpr evaluation unless
> that flag is set or it is in std::allocator<T>::{,de}allocate.

Looks like there used to be a TREE_CALLS_NEW flag in TREE_LANG_FLAG_1, but
that flag is now free for CALL_EXPR.

I'll try a CALL_EXPR flag first.

> Another thing is that even with that change,
>    std::allocator<int> a;
>    auto p = a.allocate (1);
>    *p = 1;
>    a.deallocate (p, 1);
> would be accepted during constexpr evaluation, because allocate already
> has the cast which turns "heap uninit" variable into "heap " and assigns
> it a type, so there is nothing that will prevent the store from succeeding.

What's wrong with the store?

If it is fine, the better.  I'd still think that
 struct S { constexpr S () : s (0) {}; int s; };
 std::allocator<S> a;
 auto p = a.allocate (1);
 p->s = 1;
 a.deallocate (p, 1);
would still be invalid though, because that type needs constructing and
the construction didn't happen in that case.  Or:

Yes, I agree. EDG rejects that case and Daveed corrected one of my
tests which looked like the code above, so that it would be valid and
accepted by EDG.

 struct S { constexpr S () : s (0) {}; int s; };
 std::allocator<S> a;
 auto p = a.allocate (1);
 std::construct_at (p);
 p->s++; // ok
 std::destruct_at (p);
 p->s = 1; // shouldn't this be an error?
 a.deallocate (p, 1);
but I admit I haven't tried to back that up by some standard wording, just a
general principle that objects with TYPE_ADDRESSABLE types need to be
constructed first and destructed last and accesses to it are only valid in
between those in normal code and constexpr should flag any UB as errors.

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]