Patchwork Call fold_non_dependent_expr_sfinae before maybe_constant_value (PR c++/56895)

login
register
mail settings
Submitter Jakub Jelinek
Date April 10, 2013, 6:45 a.m.
Message ID <20130410064518.GA16463@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/235306/
State New
Headers show

Comments

Jakub Jelinek - April 10, 2013, 6:45 a.m.
Hi!

As discussed in the PR, these 4 places call maybe_constant_value even
when processing_template_decl, just to try harder to see if the value isn't
constant, and that may crash if fold_non_dependent_expr hasn't been called
first.  This is just optimization to get better warnings, so we don't want
that call to emit any errors, worst case we just won't emit the warnings,
so I'm using fold_non_dependent_expr_sfinae with tf_none.

Bootstrapped/regtested on x86_64-linux and i686-linux, acked by Jason in the
PR, committed to trunk and 4.8 branch.

2013-04-10  Jakub Jelinek  <jakub@redhat.com>

	PR c++/56895
	* typeck.c (cp_build_binary_op): Call fold_non_dependent_expr_sfinae
	first before calling maybe_constant_value for warn_for_div_by_zero
	or invalid shift count warning purposes.

	* g++.dg/template/arrow3.C: New test.


	Jakub

Patch

--- gcc/cp/typeck.c.jj	2013-04-04 15:03:28.000000000 +0200
+++ gcc/cp/typeck.c	2013-04-09 20:40:20.753714512 +0200
@@ -4047,8 +4047,9 @@  cp_build_binary_op (location_t location,
 	      || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
 	{
 	  enum tree_code tcode0 = code0, tcode1 = code1;
+	  tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none);
 
-	  warn_for_div_by_zero (location, maybe_constant_value (op1));
+	  warn_for_div_by_zero (location, maybe_constant_value (cop1));
 
 	  if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE)
 	    tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
@@ -4084,7 +4085,11 @@  cp_build_binary_op (location_t location,
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
-      warn_for_div_by_zero (location, maybe_constant_value (op1));
+      {
+	tree cop1 = fold_non_dependent_expr_sfinae (op1, tf_none);
+
+	warn_for_div_by_zero (location, maybe_constant_value (cop1));
+      }
 
       if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
 	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
@@ -4132,7 +4137,8 @@  cp_build_binary_op (location_t location,
 	}
       else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
 	{
-	  tree const_op1 = maybe_constant_value (op1);
+	  tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none);
+	  const_op1 = maybe_constant_value (const_op1);
 	  if (TREE_CODE (const_op1) != INTEGER_CST)
 	    const_op1 = op1;
 	  result_type = type0;
@@ -4178,7 +4184,8 @@  cp_build_binary_op (location_t location,
 	}
       else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
 	{
-	  tree const_op1 = maybe_constant_value (op1);
+	  tree const_op1 = fold_non_dependent_expr_sfinae (op1, tf_none);
+	  const_op1 = maybe_constant_value (const_op1);
 	  if (TREE_CODE (const_op1) != INTEGER_CST)
 	    const_op1 = op1;
 	  result_type = type0;
--- gcc/testsuite/g++.dg/template/arrow3.C.jj	2013-04-09 20:27:31.800321563 +0200
+++ gcc/testsuite/g++.dg/template/arrow3.C	2013-04-09 20:42:34.000000000 +0200
@@ -0,0 +1,38 @@ 
+// PR c++/56895
+// { dg-do compile }
+
+extern struct A { bool foo (); A bar (); } *a;
+
+template <int>
+int
+baz1 ()
+{
+  return 2 << (a->bar().foo() ? 1 : 0);
+}
+
+template <int>
+int
+baz2 ()
+{
+  return 2 >> (a->bar().foo() ? 1 : 0);
+}
+
+template <int>
+int
+baz3 ()
+{
+  return 10 / (a->bar().foo() ? 1 : 2);
+}
+
+template <int>
+int
+baz4 ()
+{
+  return 10 % (a->bar().foo() ? 1 : 0);
+}
+
+int
+test ()
+{
+  return baz1<0> () + baz2<0> () + baz3<0> () + baz4<0> ();
+}