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

--- Comment #14 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>:

https://gcc.gnu.org/g:6ce952188ab39e303e4f63e474b5cba83b5b12fd

commit r14-5771-g6ce952188ab39e303e4f63e474b5cba83b5b12fd
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Nov 23 09:13:37 2023 +0100

    c++: Implement C++26 P2741R3 - user-generated static_assert messages
[PR110348]

    The following patch implements the user generated static_assert messages
next
    to string literals.

    As I wrote already in the PR, in addition to looking through the paper
    I looked at the clang++ testcase for this feature implemented there from
    paper's author and on godbolt played with various parts of the testcase
    coverage below, and there are some differences between what the patch
    implements and what clang++ implements.

    The first is that clang++ diagnoses if M.size () or M.data () methods
    are present, but aren't constexpr; while the paper introduction talks about
    that, the standard wording changes don't seem to require that, all they say
    is that those methods need to exist (assuming accessible and the like)
    and be implicitly convertible to std::size_t or const char *, but rest is
    only if the static assertion fails.  If there is intent to change that
    wording, the question is how far to go, e.g. while M.size () could be
    constexpr, they could e.g. return some class object which wouldn't have
    constexpr conversion operator to size_t/const char * and tons of other
    reasons why the constant evaluation could fail.  Without actually
evaluating
    it I don't see how we could guarantee anything for non-failed
static_assert.

    The second difference is that
    static_assert (false, "foo"_myd);
    in the testcase is normal failed static assertion and
    static_assert (true, "foo"_myd);
    would be accepted, while clang++ rejects it.  IMHO
    "foo"_myd doesn't match the syntactic requirements of unevaluated-string
    as mentioned in http://eel.is/c++draft/dcl.pre#10 , and because
    a constexpr udlit operator can return something which is valid, it
shouldn't
    be rejected just in case.
    Last is clang++ ICEs on non-static data members size/data.

    The first version of this support had a difference where M.data () was not
    a constant expression but a core constant expression, but if M.size () != 0
    M.data ()[0] ... M.data ()[M.size () - 1] were integer constant
expressions.
    We don't have any routine to test whether an expression is a core constant
    expression, so what the code does is try silently whether M.data () is
    a constant expression (maybe_constant_value), if it is, nice, we can use
    that result to attempt to optimize the extraction of the message from it
    if it is some recognized form involving a STRING_CST and just to
double-check
    try to constant evaluate M.data ()[0] and M.data ()[M.size () - 1]
expressions
    as boundaries but not anything in between.  If M.data () is not a constant
    expression, we don't fail, but use a slower method of evaluating M.data
()[i]
    for i 0, 1, ... M.size () - 1.  And if M.size () == 0, the above wouldn't
    evaluate anything, so we try to constant evaluate (M.data (), 0) as
constant
    expression, which should succeed if M.data () is a core constant expression
    and fail otherwise.

    The patch assumes that these expressions are manifestly constant evaluated.

    The patch implements what I see in the paper, because it is unclear what
    further changes will be voted in (and the changes can be done at that
    point).
    The initial patch used tf_none in 6 spots so that just the static_assert
    specific errors were emitted and not others, but during review this has
been
    changed, so that we emit both the more detailed errors why something wasn't
    found or wasn't callable or wasn't convertible and diagnostics that
    static_assert second argument needs to satisfy some of the needed
properties.

    2023-11-23  Jakub Jelinek  <ja...@redhat.com>

            PR c++/110348
    gcc/
            * doc/invoke.texi (-Wno-c++26-extensions): Document.
    gcc/c-family/
            * c.opt (Wc++26-extensions): New option.
            * c-cppbuiltin.cc (c_cpp_builtins): For C++26 predefine
            __cpp_static_assert to 202306L rather than 201411L.
    gcc/cp/
            * parser.cc: Implement C++26 P2741R3 - user-generated static_assert
            messages.
            (cp_parser_static_assert): Parse message argument as
            conditional-expression if it is not a pure string literal or
            several of them concatenated followed by closing paren.
            * semantics.cc (finish_static_assert): Handle message which is not
            STRING_CST.  For condition with bare parameter packs return early.
            * pt.cc (tsubst_expr) <case STATIC_ASSERT>: Also tsubst_expr
            message and make sure that if it wasn't originally STRING_CST, it
            isn't after tsubst_expr either.
    gcc/testsuite/
            * g++.dg/cpp26/static_assert1.C: New test.
            * g++.dg/cpp26/feat-cxx26.C (__cpp_static_assert): Expect
            202306L rather than 201411L.
            * g++.dg/cpp0x/udlit-error1.C: Expect different diagnostics for
            static_assert with user-defined literal.

Reply via email to