Bug 106649

Summary: [C++23] P2448 - Relaxing some constexpr restrictions
Product: gcc Reporter: Marek Polacek <mpolacek>
Component: c++Assignee: Marek Polacek <mpolacek>
Status: RESOLVED FIXED    
Severity: normal CC: webrown.cpp
Priority: P3    
Version: unknown   
Target Milestone: 13.0   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109623
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2022-09-29 00:00:00
Bug Depends on:    
Bug Blocks: 98940    

Description Marek Polacek 2022-08-16 16:59:59 UTC
See <https://wg21.link/p2448>.
Comment 1 GCC Commits 2022-11-16 21:31:24 UTC
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:c85f8dbb173f45053f6d8849d27adc98d9668769

commit r13-4112-gc85f8dbb173f45053f6d8849d27adc98d9668769
Author: Marek Polacek <polacek@redhat.com>
Date:   Wed Nov 2 13:11:02 2022 -0400

    c++: P2448 - Relaxing some constexpr restrictions [PR106649]
    
    This patch implements C++23 P2448, which lifts more restrictions on the
    constexpr keyword.  It's effectively going the way of being just a hint
    (hello, inline!).
    
    This gist is relatively simple: in C++23, a constexpr function's return
    type/parameter type doesn't have to be a literal type; and you can have
    a constexpr function for which no invocation satisfies the requirements
    of a core constant expression.  For example,
    
      void f(int& i); // not constexpr
    
      constexpr void g(int& i) {
        f(i); // unconditionally calls a non-constexpr function
      }
    
    is now OK, even though there isn't an invocation of 'g' that would be
    a constant expression.  Maybe 'f' will be made constexpr soon, or maybe
    this depends on the version of C++ used, and similar.  The patch is
    unfortunately not that trivial.  The important bit is to use the new
    require_potential_rvalue_constant_expression_fncheck in
    maybe_save_constexpr_fundef (and where appropriate).  It has a new flag
    that says that we're checking the body of a constexpr function, and in
    that case it's OK to find constructs that aren't a constant expression.
    
    Since it's useful to be able to check for problematic constructs even
    in C++23, this patch implements a new warning, -Winvalid-constexpr,
    which is a pedwarn turned on by default in C++20 and earlier, and which
    can be turned on in C++23 as well, in which case it's an ordinary warning.
    This I implemented by using the new function constexpr_error, used in
    p_c_e_1 and friends.  (In some cases I believe fundef_p will be always
    false (= hard error), but it made sense to me to be consistent and use
    constexpr_error throughout p_c_e_1.)
    
    While working on this I think I found a bug, see constexpr-nonlit15.C
    and <https://gcc.gnu.org/PR107598>.  This patch doesn't address that.
    
    This patch includes changes to diagnose the problem if the user doesn't
    use -Winvalid-constexpr and calls a constexpr function that in fact isn't
    constexpr-ready yet: maybe_save_constexpr_fundef registers the function
    if warn_invalid_constexpr is 0 and explain_invalid_constexpr_fn then
    gives the diagnostic.
    
            PR c++/106649
    
    gcc/c-family/ChangeLog:
    
            * c-cppbuiltin.cc (c_cpp_builtins): Update value of __cpp_constexpr for
            C++23.
            * c-opts.cc (c_common_post_options): Set warn_invalid_constexpr
            depending on cxx_dialect.
            * c.opt (Winvalid-constexpr): New option.
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (constexpr_error): New function.
            (is_valid_constexpr_fn): Use constexpr_error.
            (maybe_save_constexpr_fundef): Call
            require_potential_rvalue_constant_expression_fncheck rather than
            require_potential_rvalue_constant_expression.  Register the
            function if -Wno-invalid-constexpr was specified.
            (explain_invalid_constexpr_fn): Don't return early if a function marked
            'constexpr' that isn't actually a constant expression was called.
            (non_const_var_error): Add a bool parameter.  Use constexpr_error.
            (inline_asm_in_constexpr_error): Likewise.
            (cxx_eval_constant_expression): Adjust calls to non_const_var_error
            and inline_asm_in_constexpr_error.
            (potential_constant_expression_1): Add a bool parameter.  Use
            constexpr_error.
            (require_potential_rvalue_constant_expression_fncheck): New function.
            * cp-tree.h (require_potential_rvalue_constant_expression_fncheck):
            Declare.
            * method.cc (struct comp_info): Call
            require_potential_rvalue_constant_expression_fncheck rather than
            require_potential_rvalue_constant_expression.
    
    gcc/ChangeLog:
    
            * doc/invoke.texi: Document -Winvalid-constexpr.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/constexpr-ctor2.C: Expect an error in c++20_down only.
            * g++.dg/cpp0x/constexpr-default-ctor.C: Likewise.
            * g++.dg/cpp0x/constexpr-diag3.C: Likewise.
            * g++.dg/cpp0x/constexpr-ex1.C: Likewise.
            * g++.dg/cpp0x/constexpr-friend.C: Likewise.
            * g++.dg/cpp0x/constexpr-generated1.C: Likewise.
            * g++.dg/cpp0x/constexpr-ice5.C: Likewise.
            * g++.dg/cpp0x/constexpr-ice6.C: Likewise.
            * g++.dg/cpp0x/constexpr-memfn1.C: Likewise.
            * g++.dg/cpp0x/constexpr-neg2.C: Likewise.
            * g++.dg/cpp0x/constexpr-non-const-arg.C: Likewise.
            * g++.dg/cpp0x/constexpr-reinterpret1.C: Likewise.
            * g++.dg/cpp0x/pr65327.C: Likewise.
            * g++.dg/cpp1y/constexpr-105050.C: Likewise.
            * g++.dg/cpp1y/constexpr-89285-2.C: Likewise.
            * g++.dg/cpp1y/constexpr-89285.C: Likewise.
            * g++.dg/cpp1y/constexpr-89785-2.C: Likewise.
            * g++.dg/cpp1y/constexpr-neg1.C: Likewise.
            * g++.dg/cpp1y/constexpr-nsdmi7b.C: Likewise.
            * g++.dg/cpp1y/constexpr-throw.C: Likewise.
            * g++.dg/cpp23/constexpr-nonlit3.C: Remove dg-error.
            * g++.dg/cpp23/constexpr-nonlit6.C: Call the test functions.
            * g++.dg/cpp23/feat-cxx2b.C: Adjust the expected value of
            __cpp_constexpr.
            * g++.dg/cpp2a/consteval3.C: Remove dg-error.
            * g++.dg/cpp2a/constexpr-new7.C: Expect an error in c++20_down only.
            * g++.dg/cpp2a/constexpr-try5.C: Remove dg-error.
            * g++.dg/cpp2a/spaceship-constexpr1.C: Expect an error in c++20_down
            only.
            * g++.dg/cpp2a/spaceship-eq3.C: Likewise.
            * g++.dg/diagnostic/constexpr1.C: Remove dg-error.
            * g++.dg/gomp/pr79664.C: Use -Winvalid-constexpr -pedantic-errors.
            * g++.dg/ubsan/vptr-4.C: Likewise.
            * g++.dg/cpp23/constexpr-nonlit10.C: New test.
            * g++.dg/cpp23/constexpr-nonlit11.C: New test.
            * g++.dg/cpp23/constexpr-nonlit12.C: New test.
            * g++.dg/cpp23/constexpr-nonlit13.C: New test.
            * g++.dg/cpp23/constexpr-nonlit14.C: New test.
            * g++.dg/cpp23/constexpr-nonlit15.C: New test.
            * g++.dg/cpp23/constexpr-nonlit16.C: New test.
            * g++.dg/cpp23/constexpr-nonlit8.C: New test.
            * g++.dg/cpp23/constexpr-nonlit9.C: New test.
Comment 2 Marek Polacek 2022-11-16 21:36:24 UTC
Done for GCC 13.