c++: P2448 - Relaxing some constexpr restrictions [PR106649]
commitc85f8dbb173f45053f6d8849d27adc98d9668769
authorMarek Polacek <polacek@redhat.com>
Wed, 2 Nov 2022 17:11:02 +0000 (2 13:11 -0400)
committerMarek Polacek <polacek@redhat.com>
Wed, 16 Nov 2022 21:29:09 +0000 (16 16:29 -0500)
tree5709041b56579f5b413fcd128f85d39accfd9554
parentdbdce6adb748b95be219f2f5fb97f844a0f9b840
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.
47 files changed:
gcc/c-family/c-cppbuiltin.cc
gcc/c-family/c-opts.cc
gcc/c-family/c.opt
gcc/cp/constexpr.cc
gcc/cp/cp-tree.h
gcc/cp/method.cc
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C
gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-neg2.C
gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C
gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
gcc/testsuite/g++.dg/cpp0x/pr65327.C
gcc/testsuite/g++.dg/cpp1y/constexpr-105050.C
gcc/testsuite/g++.dg/cpp1y/constexpr-89285-2.C
gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C
gcc/testsuite/g++.dg/cpp1y/constexpr-89785-2.C
gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
gcc/testsuite/g++.dg/cpp1y/constexpr-nsdmi7b.C
gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/constexpr-nonlit9.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
gcc/testsuite/g++.dg/cpp2a/consteval3.C
gcc/testsuite/g++.dg/cpp2a/constexpr-new7.C
gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
gcc/testsuite/g++.dg/diagnostic/constexpr1.C
gcc/testsuite/g++.dg/gomp/pr79664.C
gcc/testsuite/g++.dg/ubsan/vptr-4.C