From 1e89178889741c9c4d6a61e5a01c40a8a182fa68 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Mon, 4 May 2020 18:34:38 -0400 Subject: [PATCH] c++: ICE in value_dependent_expression_p in C++98 mode [PR94938] 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. Fixed by using type_dependent_expression_p_push instead. This means that we won't suppress the warnings for value-dependent expressions that aren't type-dependent, e.g. sizeof (T). This only seems to make a difference for -Wdiv-by-zero, now tested in Wdiv-by-zero-3.C, where I think it's reasonable to warn. It could make -Wtautological-compare warn more, but that warning doesn't trigger when it gets constant arguments. Wtype-limits4.C is a test reduced from poly-int.h and it tests a scenario that was missing in our testsuite. This patch also moves the warning_sentinels after the RECURs -- we mean to use them for build_x_binary_op purposes only. PR c++/94938 * pt.c (tsubst_copy_and_build): Call type_dependent_expression_p_push instead of uses_template_parms. Move the warning_sentinels after the RECURs. * g++.dg/warn/Wdiv-by-zero-3.C: New test. * g++.dg/warn/Wtype-limits4.C: New test. * g++.dg/warn/template-2.C: New test. * g++.old-deja/g++.pt/crash10.C: Add dg-warning. --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/pt.c | 8 +++++--- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C | 17 +++++++++++++++++ gcc/testsuite/g++.dg/warn/Wtype-limits4.C | 23 +++++++++++++++++++++++ gcc/testsuite/g++.dg/warn/template-2.C | 22 ++++++++++++++++++++++ gcc/testsuite/g++.old-deja/g++.pt/crash10.C | 1 + 7 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C create mode 100644 gcc/testsuite/g++.dg/warn/Wtype-limits4.C create mode 100644 gcc/testsuite/g++.dg/warn/template-2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a3bec1c..0798f0f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-05-06 Marek Polacek + + PR c++/94938 + * pt.c (tsubst_copy_and_build): Call type_dependent_expression_p_push + instead of uses_template_parms. Move the warning_sentinels after the + RECURs. + 2020-05-06 Jakub Jelinek PR c++/94951 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2ed6d0e..c609112 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19424,14 +19424,16 @@ 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); + bool was_dep = type_dependent_expression_p_push (t); + + tree op0 = RECUR (TREE_OPERAND (t, 0)); + tree op1 = RECUR (TREE_OPERAND (t, 1)); + 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); warning_sentinel s4(warn_tautological_compare, was_dep); - tree op0 = RECUR (TREE_OPERAND (t, 0)); - tree op1 = RECUR (TREE_OPERAND (t, 1)); tree r = build_x_binary_op (input_location, TREE_CODE (t), op0, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7e28d9a..b6b0441 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2020-05-06 Marek Polacek + + PR c++/94938 + * g++.dg/warn/Wdiv-by-zero-3.C: New test. + * g++.dg/warn/Wtype-limits4.C: New test. + * g++.dg/warn/template-2.C: New test. + * g++.old-deja/g++.pt/crash10.C: Add dg-warning. + 2020-05-06 Iain Buclaw PR d/94970 diff --git a/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C b/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C new file mode 100644 index 0000000..424eb0c --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C @@ -0,0 +1,17 @@ +// PR c++/94938 + +template int +foo (T t, int i) +{ + int m1 = 10 / t; + int m2 = 10 / i; + int m3 = 10 / (sizeof(T) - sizeof(int)); // { dg-warning "division by" } + int m4 = 10 / N; // { dg-warning "division by" } + return m1 + m2 + m3 + m4; +} + +void +f () +{ + foo(0, 0); +} diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits4.C b/gcc/testsuite/g++.dg/warn/Wtype-limits4.C new file mode 100644 index 0000000..3ae44b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wtype-limits4.C @@ -0,0 +1,23 @@ +// PR c++/94938 +// { dg-additional-options "-Wtype-limits" } + +template struct B { unsigned arr[N]; }; +template<> struct B<1u> { int arr[10]; }; + +template bool +foo(B l) +{ + int i = 0; + return l.arr[i] < 0; +} + +void +j() +{ + B<1u> b; + foo (b); + B<2u> b2; + // I think that in this instantiation we could warn, but it breaks + // gcc bootstrap (marek 5/2020). + foo (b2); +} 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 0000000..1d29528 --- /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 struct S { S(); S(bool); }; + +struct C { + bool operator()(S); +}; + +S fn (bool); + +template void +foo (T) +{ + S s; + S x = fn(false || C()(s)); +} + +int main () +{ + foo(int()); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C index a84b190..012e3d0 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C @@ -6,6 +6,7 @@ public: enum { val = (N == 0) ? M : GCD::val }; // { dg-error "constant expression" "valid" { target *-*-* } .-1 } // { dg-message "template argument" "valid" { target *-*-* } .-2 } +// { dg-warning "division by" "" { target *-*-* } .-3 } }; int main() { -- 2.7.4