https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110348

corentinjabot at gmail dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |corentinjabot at gmail dot com

--- Comment #9 from corentinjabot at gmail dot com ---
(In reply to Jakub Jelinek from comment #3)
> I wonder if the paper wording isn't incorrect, or at least comparing the
> clang++
> implementation vs. the paper gives some differences.
> 
> One (minor) is that they emit errors when the size () and/or data () members
> aren't constexpr, while the paper as voted in only requires that
> "- the expression M.size() is implicitly convertible to std::size_t, and
> - the expression M.data() is implicitly convertible to ”pointer to const
> char”."
> unless the static assertion fails.  The WIP patch doesn't do that, only
> effectively diagnoses it during constant evaluation of those when the static
> assertion fails.

During review in clang we felt that it diagnosing it it all cases
would be preferable to our users, as otherwise errors only manifest when the
static assertion fails,
likely at a point where the person getting the diagnostic would not be able to
act on it.
So we made it a warning that defaults to an error.

Note that core felt strongly we should not check for constant expressions at
the time, 
but maybe opinions changed?

> 
> More important, they have in the testcase something similar to what I filed
> in PR111122, but let's use what works also in GCC:
> struct T {
>   const char *d = init ();
>   constexpr int size () const { return 2; }
>   constexpr const char *data () const { return d; }
>   constexpr const char *init () const { return new char[2] { 'o', 'k' }; }
>   constexpr ~T () { delete[] d; }
> };
> constexpr int a = T{}.size (); // Ok, a = 2
> constexpr int b = T{}.data ()[0]; // Ok, b = 'o'
> constexpr const char *c = T{}.data (); // Not constant expression, because
> it returns
> // address from new which is later in the dtor deleted.
> static_assert (false, T{}); // Valid?


See https://github.com/cplusplus/CWG/issues/350, because i was confused too.
`data()` is a core constant expression. the implementation should behave _as
if_ `T{}.data ()[N]` is evaluated for each `N`
even if that would be pretty bad implementation strategy.

> 
> "- M.data(), implicitly converted to the type ”pointer to const char”, shall
> be a core
> constant expression and let D denote the converted expression,
> 
> – for each i where 0 ≤ i < N , D[i] shall be an integral constant
> expression, and"
> 
> Now, I believe T{}.data () is not a core constant expression exactly because
> it returns address of later deleted heap object, but sure, both T{}.data
> ()[0] and T{}.data ()[1]
> are integral constant expressions.
> 
> I don't know how std::format if constexpr (is it?) or string_view etc. work,
> do they
> need M.data () not be actual constant expression and only M.data ()[0]
> through M.data ()[M.size () - 1] constant expressions?  In the patch I can
> surely try to constant expr evaluate M.data () quietly and if it isn't
> constant expression, just use a slower way which will ask for each character
> individually.  More important question is what is the intention for the
> standard...

Reply via email to