diff mbox

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

Message ID 20130410064518.GA16463@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek April 10, 2013, 6:45 a.m. UTC
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
diff mbox

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> ();
+}