Here we ICE with -std=c++98 since the newly added call to uses_template_parms (r10-6357): we hit 26530 gcc_assert (cxx_dialect >= cxx11 26531 || INTEGRAL_OR_ENUMERATION_TYPE_P (type)); and TYPE is a record type. The problem is that the argument to value_dependent_expression_p does not satisfy potential_constant_expression which it must, as the comment explains. I thought about fixing this in uses_template_parms -- only call v_d_e_p if p_c_e is true, but in this case we want to also suppress the warnings if we don't have a constant expression. I couldn't simply check TREE_CONSTANT as in compute_array_index_type_loc, because then we'd stop warning in the new Wtype-limits3.C test.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10? PR c++/94938 * pt.c (tsubst_copy_and_build): Don't call value_dependent_expression_p if the expression is not potential_constant_expression. * g++.dg/warn/template-2.C: New test. --- gcc/cp/pt.c | 5 ++++- gcc/testsuite/g++.dg/warn/template-2.C | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/warn/template-2.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 61cb75bf801..691f6e4df36 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19423,7 +19423,10 @@ tsubst_copy_and_build (tree t, { /* If T was type-dependent, suppress warnings that depend on the range of the types involved. */ - bool was_dep = uses_template_parms (t); + ++processing_template_decl; + bool was_dep = (!potential_constant_expression (t) + || value_dependent_expression_p (t)); + --processing_template_decl; warning_sentinel s1(warn_type_limits, was_dep); warning_sentinel s2(warn_div_by_zero, was_dep); warning_sentinel s3(warn_logical_op, was_dep); diff --git a/gcc/testsuite/g++.dg/warn/template-2.C b/gcc/testsuite/g++.dg/warn/template-2.C new file mode 100644 index 00000000000..1d29528b2ac --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/template-2.C @@ -0,0 +1,22 @@ +// PR c++/94938 - ICE in value_dependent_expression_p in C++98 mode. +// { dg-do compile } + +template <typename> struct S { S(); S(bool); }; + +struct C { + bool operator()(S<float>); +}; + +S<float> fn (bool); + +template<typename T> void +foo (T) +{ + S<float> s; + S<float> x = fn(false || C()(s)); +} + +int main () +{ + foo(int()); +} base-commit: 5e681acd3587285cc3c8c6d603e4ce93cf6dacf2 -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA