public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "cvs-commit at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/107687] [C++23] P2564 - consteval needs to propagate up
Date: Tue, 05 Dec 2023 00:42:36 +0000	[thread overview]
Message-ID: <bug-107687-4-3K1EPaX2T9@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-107687-4@http.gcc.gnu.org/bugzilla/>

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

--- Comment #3 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:1f1c432226cf3db399b2a2a627e3c5720b02b1d6

commit r14-6129-g1f1c432226cf3db399b2a2a627e3c5720b02b1d6
Author: Marek Polacek <polacek@redhat.com>
Date:   Tue Sep 19 16:31:17 2023 -0400

    c++: implement P2564, consteval needs to propagate up [PR107687]

    This patch implements P2564, described at <wg21.link/p2564>, whereby
    certain functions are promoted to consteval.  For example:

      consteval int id(int i) { return i; }

      template <typename T>
      constexpr int f(T t)
      {
        return t + id(t); // id causes f<int> to be promoted to consteval
      }

      void g(int i)
      {
        f (3);
      }

    now compiles.  Previously the code was ill-formed: we would complain
    that 't' in 'f' is not a constant expression.  Since 'f' is now
    consteval, it means that the call to id(t) is in an immediate context,
    so doesn't have to produce a constant -- this is how we allow consteval
    functions composition.  But making 'f<int>' consteval also means that
    the call to 'f' in 'g' must yield a constant; failure to do so results
    in an error.  I made the effort to have cc1plus explain to us what's
    going on.  For example, calling f(i) produces this neat diagnostic:

    w.C:11:11: error: call to consteval function 'f<int>(i)' is not a constant
expression
       11 |         f (i);
          |         ~~^~~
    w.C:11:11: error: 'i' is not a constant expression
    w.C:6:22: note: 'constexpr int f(T) [with T = int]' was promoted to an
immediate function because its body contains an immediate-escalating expression
'id(t)'
        6 |         return t + id(t); // id causes f<int> to be promoted to
consteval
          |                    ~~^~~

    which hopefully makes it clear what's going on.

    Implementing this proposal has been tricky.  One problem was delayed
    instantiation: instantiating a function can set off a domino effect
    where one call promotes a function to consteval but that then means
    that another function should also be promoted, etc.

    In v1, I addressed the delayed instantiation problem by instantiating
    trees early, so that we can escalate functions right away.  That caused
    a number of problems, and in certain cases, like consteval-prop3.C, it
    can't work, because we need to wait till EOF to see the definition of
    the function anyway.  Overeager instantiation tends to cause diagnostic
    problems too.

    In v2, I attempted to move the escalation to the gimplifier, at which
    point all templates have been instantiated.  That attempt flopped,
    however, because once we've gimplified a function, its body is discarded
    and as a consequence, you can no longer evaluate a call to that function
    which is required for escalating, which needs to decide if a call is
    a constant expression or not.

    Therefore, we have to perform the escalation before gimplifying, but
    after instantiate_pending_templates.  That's not easy because we have
    no way to walk all the trees.  In the v2 patch, I use two vectors: one
    to store function decls that may become consteval, and another to
    remember references to immediate-escalating functions.  Unfortunately
    the latter must also stash functions that call immediate-escalating
    functions.  Consider:

      int g(int i)
      {
        f<int>(i); // f is immediate-escalating
      }

    where g itself is not immediate-escalating, but we have to make sure
    that if f gets promoted to consteval, we give an error.

    A new option, -fno-immediate-escalation, is provided to suppress
    escalating functions.

    v2 also adds a new flag, DECL_ESCALATION_CHECKED_P, so that we don't
    escalate a function multiple times, and so that we can distinguish between
    explicitly consteval functions and functions that have been promoted
    to consteval.

    In v3, I removed one of the new vectors and changed the other one
    to a hash set.  This version also contains numerous cleanups.

    v4 merges find_escalating_expr_r into cp_fold_immediate_r.  It also
    adds a new optimization in cp_fold_function.

    v5 greatly simplifies the code.

    v6 simplifies the code further and removes an ff_ flag.

    v7 removes maybe_promote_function_to_consteval and further simplifies
    cp_fold_immediate_r logic.

    v8 removes maybe_store_immediate_escalating_fn.

            PR c++/107687
            PR c++/110997

    gcc/c-family/ChangeLog:

            * c-cppbuiltin.cc (c_cpp_builtins): Update __cpp_consteval.
            * c-opts.cc (c_common_post_options): Pre-C++20, unset
            flag_immediate_escalation.
            * c.opt (fimmediate-escalation): New option.

    gcc/cp/ChangeLog:

            * call.cc (in_immediate_context): No longer static.
            * constexpr.cc (cxx_eval_call_expression): Adjust assert.
            * cp-gimplify.cc (deferred_escalating_exprs): New vec.
            (remember_escalating_expr): New.
            (enum fold_flags): Remove ff_fold_immediate.
            (immediate_escalating_function_p): New.
            (unchecked_immediate_escalating_function_p): New.
            (promote_function_to_consteval): New.
            (cp_fold_immediate): Move above.  Return non-null if any errors
were
            emitted.
            (maybe_explain_promoted_consteval): New.
            (cp_gimplify_expr) <case CALL_EXPR>: Assert we've handled all
            immediate invocations.
            (taking_address_of_imm_fn_error): New.
            (cp_fold_immediate_r): Merge ADDR_EXPR and PTRMEM_CST cases. 
Implement
            P2564 - promoting functions to consteval.
            <case CALL_EXPR>: Implement P2564 - promoting functions to
consteval.
            (cp_fold_r): If an expression turns into a CALL_EXPR after cp_fold,
            call cp_fold_immediate_r on the CALL_EXPR.
            (cp_fold_function): Set DECL_ESCALATION_CHECKED_P if
            deferred_escalating_exprs does not contain current_function_decl.
            (process_and_check_pending_immediate_escalating_fns): New.
            * cp-tree.h (struct lang_decl_fn): Add escalated_p bit-field.
            (DECL_ESCALATION_CHECKED_P): New.
            (immediate_invocation_p): Declare.
            (process_pending_immediate_escalating_fns): Likewise.
            * decl2.cc (c_parse_final_cleanups): Set at_eof to 2 after all
            templates have been instantiated; and to 3 at the end of the
function.
            Call process_pending_immediate_escalating_fns.
            * error.cc (dump_template_bindings): Check at_eof against an
updated
            value.
            * module.cc (trees_out::lang_decl_bools): Stream escalated_p.
            (trees_in::lang_decl_bools): Likewise.
            * pt.cc (push_tinst_level_loc): Set at_eof to 3, not 2.
            * typeck.cc (cp_build_addr_expr_1): Don't check
            DECL_IMMEDIATE_FUNCTION_P.

    gcc/ChangeLog:

            * doc/invoke.texi: Document -fno-immediate-escalation.

    libstdc++-v3/ChangeLog:

            * testsuite/18_support/comparisons/categories/zero_neg.cc: Add
            dg-prune-output.
            * testsuite/std/format/string_neg.cc: Add dg-error.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp23/consteval-if10.C: Remove dg-error.
            * g++.dg/cpp23/consteval-if2.C: Likewise.
            * g++.dg/cpp23/feat-cxx2b.C: Adjust expected value of
__cpp_consteval.
            * g++.dg/cpp26/feat-cxx26.C: Likewise.
            * g++.dg/cpp2a/consteval-memfn1.C: Add dg-error.
            * g++.dg/cpp2a/consteval11.C: Likewise.
            * g++.dg/cpp2a/consteval3.C: Adjust dg-error.
            * g++.dg/cpp2a/consteval34.C: Add dg-error.
            * g++.dg/cpp2a/consteval36.C: Likewise.
            * g++.dg/cpp2a/consteval9.C: Likewise.
            * g++.dg/cpp2a/feat-cxx2a.C: Adjust expected value of
__cpp_consteval.
            * g++.dg/cpp2a/spaceship-synth9.C: Adjust dg-error.
            * g++.dg/cpp2a/consteval-prop1.C: New test.
            * g++.dg/cpp2a/consteval-prop10.C: New test.
            * g++.dg/cpp2a/consteval-prop11.C: New test.
            * g++.dg/cpp2a/consteval-prop12.C: New test.
            * g++.dg/cpp2a/consteval-prop13.C: New test.
            * g++.dg/cpp2a/consteval-prop14.C: New test.
            * g++.dg/cpp2a/consteval-prop15.C: New test.
            * g++.dg/cpp2a/consteval-prop16.C: New test.
            * g++.dg/cpp2a/consteval-prop17.C: New test.
            * g++.dg/cpp2a/consteval-prop18.C: New test.
            * g++.dg/cpp2a/consteval-prop19.C: New test.
            * g++.dg/cpp2a/consteval-prop20.C: New test.
            * g++.dg/cpp2a/consteval-prop2.C: New test.
            * g++.dg/cpp2a/consteval-prop3.C: New test.
            * g++.dg/cpp2a/consteval-prop4.C: New test.
            * g++.dg/cpp2a/consteval-prop5.C: New test.
            * g++.dg/cpp2a/consteval-prop6.C: New test.
            * g++.dg/cpp2a/consteval-prop7.C: New test.
            * g++.dg/cpp2a/consteval-prop8.C: New test.
            * g++.dg/cpp2a/consteval-prop9.C: New test.

  parent reply	other threads:[~2023-12-05  0:42 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-14 18:36 [Bug c++/107687] New: " mpolacek at gcc dot gnu.org
2022-11-14 18:36 ` [Bug c++/107687] " mpolacek at gcc dot gnu.org
2023-08-10 22:58 ` mpolacek at gcc dot gnu.org
2023-08-11 19:39 ` mpolacek at gcc dot gnu.org
2023-12-05  0:42 ` cvs-commit at gcc dot gnu.org [this message]
2023-12-05  0:44 ` mpolacek at gcc dot gnu.org
2023-12-05  0:45 ` mpolacek at gcc dot gnu.org
2024-01-12  7:38 ` rguenth at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-107687-4-3K1EPaX2T9@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).