mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
c++: Fix up convert_nontype_argument [PR124070]
Some of the following testcases are incorrectly accepted.
The problem is in convert_nontype_argument. It just does
maybe_constant_value earlier. Later on for integral/enum/floating
point args it uses cxx_constant_value for complain & tf_error if
not val_dep_p and expr is not a simple constant, similarly for
class type it calls
/* Replace the argument with a reference to the corresponding template
parameter object. */
if (!val_dep_p)
expr = create_template_parm_object (expr, complain);
if (expr == error_mark_node)
return NULL_TREE;
etc. But for NULLPTR_TYPE_P and REFLECTION_TYPE_P cases (I bet
Marek has based the latter on the former) it only verifies the type
and not the actual expression.
I think we need to do that, because if maybe_constant_value fails, it
just returns the passed in argument and if nothing checks it, we accept
whatever was there (and sometimes ICE later).
The following patch implements that.
2026-02-19 Jakub Jelinek <jakub@redhat.com>
PR c++/124070
* pt.cc (convert_nontype_argument): For NULLPTR_TYPE_P case
if expr is not integer_zerop and is not val_dep_p try harder,
for complain & tf_error use cxx_constant_value and return NULL_TREE
for error_mark_node, without tf_error return NULL_TREE. Similarly
for REFLECTION_TYPE_P case if expr is not REFLECT_EXPR and is not
val_dep_p try harder like for NULLPTR_TYPE_P.
* g++.dg/cpp26/pr124070.C: New test.
* g++.dg/reflect/parameters_of4.C: Expect different diagnostics.
* g++.dg/reflect/define_aggregate7.C: New test.
* g++.dg/reflect/define_aggregate8.C: New test.
This commit is contained in:
committed by
Jakub Jelinek
parent
3cd8377957
commit
cb617bedc8
24
gcc/cp/pt.cc
24
gcc/cp/pt.cc
@@ -8017,6 +8017,18 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
|
||||
"because it is of type %qT", expr, type, TREE_TYPE (expr));
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (!integer_zerop (expr) && !val_dep_p)
|
||||
{
|
||||
if (complain & tf_error)
|
||||
{
|
||||
expr = cxx_constant_value (expr);
|
||||
if (expr == error_mark_node)
|
||||
return NULL_TREE;
|
||||
gcc_assert (integer_zerop (expr));
|
||||
}
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
else if (CLASS_TYPE_P (type))
|
||||
@@ -8037,6 +8049,18 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
|
||||
"because it is of type %qT", expr, type, TREE_TYPE (expr));
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (!REFLECT_EXPR_P (expr) && !val_dep_p)
|
||||
{
|
||||
if (complain & tf_error)
|
||||
{
|
||||
expr = cxx_constant_value (expr);
|
||||
if (expr == error_mark_node)
|
||||
return NULL_TREE;
|
||||
gcc_assert (REFLECT_EXPR_P (expr));
|
||||
}
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
/* A template non-type parameter must be one of the above. */
|
||||
|
||||
20
gcc/testsuite/g++.dg/cpp26/pr124070.C
Normal file
20
gcc/testsuite/g++.dg/cpp26/pr124070.C
Normal file
@@ -0,0 +1,20 @@
|
||||
// PR c++/124070
|
||||
// { dg-do compile { target c++26 } }
|
||||
|
||||
constexpr decltype (nullptr)
|
||||
bar (bool x)
|
||||
{
|
||||
if (x)
|
||||
throw 1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <decltype (nullptr) I = bar (true)> // { dg-error "uncaught exception '1'" }
|
||||
constexpr void
|
||||
foo ()
|
||||
{
|
||||
}
|
||||
|
||||
consteval {
|
||||
foo <> (); // { dg-error "no matching function for call to 'foo<>\\\(\\\)'" }
|
||||
}
|
||||
13
gcc/testsuite/g++.dg/reflect/define_aggregate7.C
Normal file
13
gcc/testsuite/g++.dg/reflect/define_aggregate7.C
Normal file
@@ -0,0 +1,13 @@
|
||||
// PR c++/124070
|
||||
// { dg-do compile { target c++26 } }
|
||||
// { dg-additional-options "-freflection" }
|
||||
|
||||
#include <meta>
|
||||
|
||||
struct S;
|
||||
template <std::meta::info I = define_aggregate (^^S, {})> // { dg-error "'define_aggregate' not evaluated from 'consteval' block" }
|
||||
constexpr void foo () {}
|
||||
|
||||
consteval {
|
||||
foo <> (); // { dg-error "no matching function for call to 'foo<>\\\(\\\)'" }
|
||||
}
|
||||
12
gcc/testsuite/g++.dg/reflect/define_aggregate8.C
Normal file
12
gcc/testsuite/g++.dg/reflect/define_aggregate8.C
Normal file
@@ -0,0 +1,12 @@
|
||||
// PR c++/124070
|
||||
// { dg-do compile { target c++26 } }
|
||||
// { dg-additional-options "-freflection" }
|
||||
|
||||
#include <meta>
|
||||
|
||||
struct S;
|
||||
consteval void bar (std::meta::info a = define_aggregate (^^S, {})) {}
|
||||
consteval {
|
||||
bar ();
|
||||
}
|
||||
S s;
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
#include <meta>
|
||||
|
||||
template<auto R> void foo () {} // { dg-message "sorry, unimplemented: mangling" }
|
||||
template<auto R> void foo () {}
|
||||
void
|
||||
g ()
|
||||
{
|
||||
foo<std::meta::parameters_of(^^g)[0]>();
|
||||
foo<std::meta::parameters_of(^^g)[0]>(); // { dg-error "no matching function for call to" }
|
||||
}
|
||||
// { dg-error "call to non-'constexpr' function" "" { target *-*-* } 0 }
|
||||
|
||||
Reference in New Issue
Block a user