c++: always check consteval address
The restriction on the "permitted result of a constant expression" to not refer to an immediate function applies regardless of context. The previous code tried to only check in cases where we wouldn't get the check in cp_fold_r, but with the next patch I would need to add another case and it shouldn't be a problem to always check. We also shouldn't talk about immediate evaluation when we aren't dealing with one. gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_outermost_constant_expr): Always check for address of immediate fn. (maybe_constant_init_1): Evaluate PTRMEM_CST. gcc/testsuite/ChangeLog: * g++.dg/DRs/dr2478.C: Handle -fimplicit-constexpr. * g++.dg/cpp23/consteval-if12.C: Adjust diagnostics. * g++.dg/cpp2a/consteval20.C: Likewise. * g++.dg/cpp2a/consteval24.C: Likewise. * g++.dg/cpp2a/srcloc20.C: Likewise.
This commit is contained in:
parent
a056a9868e
commit
688fdde2f1
6 changed files with 37 additions and 26 deletions
|
@ -8353,7 +8353,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
|
|||
non_constant_p = true;
|
||||
}
|
||||
|
||||
if (!global_ctx.heap_vars.is_empty ())
|
||||
if (!non_constant_p && cxx_dialect >= cxx20
|
||||
&& !global_ctx.heap_vars.is_empty ())
|
||||
{
|
||||
tree heap_var = cp_walk_tree_without_duplicates (&r, find_heap_var_refs,
|
||||
NULL);
|
||||
|
@ -8384,15 +8385,22 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
|
|||
|
||||
/* Check that immediate invocation does not return an expression referencing
|
||||
any immediate function decls. */
|
||||
if (is_consteval || in_immediate_context ())
|
||||
if (!non_constant_p && cxx_dialect >= cxx20)
|
||||
if (tree immediate_fndecl
|
||||
= cp_walk_tree_without_duplicates (&r, find_immediate_fndecl,
|
||||
NULL))
|
||||
{
|
||||
if (!allow_non_constant && !non_constant_p)
|
||||
error_at (cp_expr_loc_or_input_loc (t),
|
||||
"immediate evaluation returns address of immediate "
|
||||
"function %qD", immediate_fndecl);
|
||||
{
|
||||
if (is_consteval)
|
||||
error_at (cp_expr_loc_or_input_loc (t),
|
||||
"immediate evaluation returns address of immediate "
|
||||
"function %qD", immediate_fndecl);
|
||||
else
|
||||
error_at (cp_expr_loc_or_input_loc (t),
|
||||
"constant evaluation returns address of immediate "
|
||||
"function %qD", immediate_fndecl);
|
||||
}
|
||||
r = t;
|
||||
non_constant_p = true;
|
||||
}
|
||||
|
@ -8795,8 +8803,8 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
|
|||
t = TARGET_EXPR_INITIAL (t);
|
||||
if (!is_nondependent_static_init_expression (t))
|
||||
/* Don't try to evaluate it. */;
|
||||
else if (CONSTANT_CLASS_P (t) && allow_non_constant)
|
||||
/* No evaluation needed. */;
|
||||
else if (CONSTANT_CLASS_P (t) && TREE_CODE (t) != PTRMEM_CST)
|
||||
/* No evaluation needed. PTRMEM_CST needs the immediate fn check. */;
|
||||
else
|
||||
{
|
||||
/* [basic.start.static] allows constant-initialization of variables with
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
// DR 2478 - Properties of explicit specializations of implicitly-instantiated class templates
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
// Defeat -fimplicit-constexpr
|
||||
int ii;
|
||||
|
||||
template <typename T>
|
||||
struct S {
|
||||
int foo () { return 0; }
|
||||
int foo () { return ii; }
|
||||
constexpr int bar () { return 0; }
|
||||
int baz () { return 0; }
|
||||
int baz () { return ii; }
|
||||
consteval int qux () { return 0; }
|
||||
constexpr S () {}
|
||||
static constinit T x;
|
||||
|
@ -14,7 +17,7 @@ struct S {
|
|||
|
||||
template <typename T>
|
||||
T S<T>::x = S<T> ().foo (); // { dg-error "'constinit' variable 'S<char>::x' does not have a constant initializer" }
|
||||
// { dg-error "call to non-'constexpr' function" "" { target *-*-* } .-1 }
|
||||
// { dg-error "call to non-'constexpr' function|called in a constant expression" "" { target *-*-* } .-1 }
|
||||
|
||||
template <typename T>
|
||||
T S<T>::y = S<T> ().foo ();
|
||||
|
@ -49,14 +52,14 @@ S<char>::qux ()
|
|||
|
||||
template <>
|
||||
long S<long>::x = S<long> ().foo (); // { dg-bogus "'constinit' variable 'S<long int>::x' does not have a constant initializer" "" { xfail *-*-* } }
|
||||
// { dg-bogus "call to non-'constexpr' function" "" { xfail *-*-* } .-1 }
|
||||
// { dg-bogus "call to non-'constexpr' function|called in a constant expression" "" { xfail *-*-* } .-1 }
|
||||
|
||||
template <>
|
||||
constinit long S<long>::y = S<long> ().foo (); // { dg-error "'constinit' variable 'S<long int>::y' does not have a constant initializer" }
|
||||
// { dg-error "call to non-'constexpr' function" "" { target *-*-* } .-1 }
|
||||
// { dg-error "call to non-'constexpr' function|called in a constant expression" "" { target *-*-* } .-1 }
|
||||
|
||||
constinit auto a = S<char> ().foo (); // { dg-error "'constinit' variable 'a' does not have a constant initializer" }
|
||||
// { dg-error "call to non-'constexpr' function" "" { target *-*-* } .-1 }
|
||||
// { dg-error "call to non-'constexpr' function|called in a constant expression" "" { target *-*-* } .-1 }
|
||||
constinit auto b = S<char> ().bar ();
|
||||
constinit auto c = S<int> ().foo ();
|
||||
constinit auto d = S<int> ().bar (); // { dg-error "'constinit' variable 'd' does not have a constant initializer" }
|
||||
|
@ -65,7 +68,7 @@ constinit auto e = S<char> ().baz ();
|
|||
constinit auto f = S<char> ().qux (); // { dg-error "'constinit' variable 'f' does not have a constant initializer" }
|
||||
// { dg-error "call to non-'constexpr' function" "" { target *-*-* } .-1 }
|
||||
constinit auto g = S<int> ().baz (); // { dg-error "'constinit' variable 'g' does not have a constant initializer" }
|
||||
// { dg-error "call to non-'constexpr' function" "" { target *-*-* } .-1 }
|
||||
// { dg-error "call to non-'constexpr' function|called in a constant expression" "" { target *-*-* } .-1 }
|
||||
constinit auto h = S<int> ().qux ();
|
||||
auto i = S<char>::x;
|
||||
auto j = S<int>::x;
|
||||
|
|
|
@ -19,10 +19,10 @@ bar ()
|
|||
{
|
||||
S s;
|
||||
if consteval { // { dg-warning "'if consteval' only available with" "" { target c++20_only } }
|
||||
constexpr auto fn1 = foo; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn2 = &foo; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn3 = &S::foo; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn4 = &S::bar; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn1 = foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn2 = &foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn3 = &S::foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn4 = &S::bar; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn5 = baz (); // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn6 = qux (); // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn7 = corge (); // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
|
|
|
@ -11,12 +11,12 @@ int
|
|||
bar ()
|
||||
{
|
||||
auto c = &S::foo; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto d = &S::foo; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto d = &S::foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
static auto e = &S::foo; // { dg-error "taking address of an immediate function" }
|
||||
return (s.*&S::foo) (); // { dg-error "taking address of an immediate function" }
|
||||
}
|
||||
|
||||
constexpr auto a = &S::foo; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto a = &S::foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
auto b = &S::foo; // { dg-error "taking address of an immediate function" }
|
||||
|
||||
consteval int
|
||||
|
|
|
@ -17,10 +17,10 @@ consteval int
|
|||
bar ()
|
||||
{
|
||||
S s;
|
||||
constexpr auto fn1 = foo; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn2 = &foo; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn3 = &S::foo; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn4 = &S::bar; // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn1 = foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn2 = &foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn3 = &S::foo; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn4 = &S::bar; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
constexpr auto fn5 = baz (); // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn6 = qux (); // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
constexpr auto fn7 = corge (); // { dg-error "immediate evaluation returns address of immediate function" }
|
||||
|
|
|
@ -33,12 +33,12 @@ namespace std {
|
|||
using namespace std;
|
||||
|
||||
auto a = source_location::current; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto b = &source_location::current; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto b = &source_location::current; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
|
||||
void
|
||||
foo ()
|
||||
{
|
||||
auto c = &source_location::current; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto d = source_location::current; // { dg-error "taking address of an immediate function" }
|
||||
constexpr auto d = source_location::current; // { dg-error "constant evaluation returns address of immediate function" }
|
||||
static auto e = source_location::current; // { dg-error "taking address of an immediate function" }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue