On 5/5/20 5:35 PM, Marek Polacek wrote:
On Mon, May 04, 2020 at 09:18:57PM -0400, Jason Merrill wrote:
On 5/4/20 7:32 PM, Marek Polacek wrote:
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;
Hmm, it seems weird to condition the warning on whether or not the
expression is constant.
Do we want type_dependent_expression_p or
instantiation_dependent_expression_p here?
So the question is essentially do we want to suppress the warnings for
value-dependent but not type-dependent expressions, like sizeof (T)? I think
we don't need to, the second paragraph in my commit message explains why.
clang++ also warns for the new Wdiv-by-zero-3.C test. Further, we already have
a _push variant of type_dependent_expression_p which is convenient.
I also wonder if we want to move the warning_sentinels after the RECURs.
...because we only mean to use them for build_x_binary_op purposes, not various
tsubst_* in the RECURs? Makes sense, done.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10.2?
OK.
-- >8 --
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/pt.c | 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 +
5 files changed, 68 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/pt.c b/gcc/cp/pt.c
index ff8391c2093..b1a3317b62e 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/g++.dg/warn/Wdiv-by-zero-3.C
b/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C
new file mode 100644
index 00000000000..424eb0c3d49
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C
@@ -0,0 +1,17 @@
+// PR c++/94938
+
+template <typename T, int N> 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<int, 0>(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 00000000000..3ae44b4f25a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits4.C
@@ -0,0 +1,23 @@
+// PR c++/94938
+// { dg-additional-options "-Wtype-limits" }
+
+template<unsigned N> struct B { unsigned arr[N]; };
+template<> struct B<1u> { int arr[10]; };
+
+template <unsigned N> bool
+foo(B<N> 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 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());
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
index a84b19004ee..012e3d0c11b 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<N, M % N>::val };
// { dg-error "constant expression" "valid" { target *-*-* } .-1 }
// { dg-message "template argument" "valid" { target *-*-* } .-2 }
+// { dg-warning "division by" "" { target *-*-* } .-3 }
};
int main() {
base-commit: e5185cc6be3da99435129cdc0c769d4081e82989