[C++ PATCH] Fix static_cast overflow handling (PR c++/23056)

Jakub Jelinek jakub@redhat.com
Mon Sep 5 11:16:00 GMT 2005


Hi!

The testcase below fails with ICE on write_template_arg_literal,
which asserts that for bool type value is either integer_zerop or
integer_onep, but due to constant sharing issue in static_cast
handling we ended up with TREE_OVERFLOW set on true and thus not
recognized by integer_onep.
There are IMHO two problems.  One is that CONSTANT_CLASS_P covers
the 4 _CST codes that have meaningful TREE_*_OVERFLOW bits, but
also STRING_CST, for which static_flag is used for something else
(not sure exactly what, fix_string_type sets TREE_STATIC unconditionally.
The other is that in presence of constant sharing we shouldn't modify
shared constants, and in case we want to clear both TREE_*OVERFLOW bits,
we should on the other side ensure the constants can be shared, as various
parts of the compiler might rely on the sharing.

Ok to commit for HEAD/4.0 (4.0/4.1 regression) if bootstrap/regtesting
succeeds?

2005-09-05  Jakub Jelinek  <jakub@redhat.com>

	PR c++/23056
	* typeck.c (buld_static_cast_1): Avoid looking at TREE_*OVERFLOW
	of STRING_CST.  Fix problems with constant sharing.

	* g++.dg/opt/pr23056.C: New test.

--- gcc/cp/typeck.c.jj	2005-09-05 11:44:02.000000000 +0200
+++ gcc/cp/typeck.c	2005-09-05 13:05:10.000000000 +0200
@@ -4630,11 +4630,25 @@ build_static_cast_1 (tree type, tree exp
 
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (result) == INTEGER_CST
-	  && CONSTANT_CLASS_P (orig))
-	{
-	  TREE_OVERFLOW (result) = TREE_OVERFLOW (orig);
-	  TREE_CONSTANT_OVERFLOW (result)
-	    = TREE_CONSTANT_OVERFLOW (orig);
+	  && CONSTANT_CLASS_P (orig)
+	  && TREE_CODE (orig) != STRING_CST
+	  && (TREE_OVERFLOW (result) != TREE_OVERFLOW (orig)
+	      || TREE_CONSTANT_OVERFLOW (result)
+		 != TREE_CONSTANT_OVERFLOW (orig)))
+	{
+	  if (!TREE_OVERFLOW (orig) && !TREE_CONSTANT_OVERFLOW (orig))
+	    /* Ensure constant sharing.  */
+	    result = build_int_cst_wide (TREE_TYPE (result),
+					 TREE_INT_CST_LOW (result),
+					 TREE_INT_CST_HIGH (result));
+	  else
+	    {
+	      /* Avoid clobbering a shared constant.  */
+	      result = copy_node (result);
+	      TREE_OVERFLOW (result) = TREE_OVERFLOW (orig);
+	      TREE_CONSTANT_OVERFLOW (result)
+		= TREE_CONSTANT_OVERFLOW (orig);
+	    }
 	}
       /* [expr.static.cast]
 
@@ -4679,10 +4693,25 @@ build_static_cast_1 (tree type, tree exp
 
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (expr) == INTEGER_CST
-	  && CONSTANT_CLASS_P (orig))
-	{
-	  TREE_OVERFLOW (expr) = TREE_OVERFLOW (orig);
-	  TREE_CONSTANT_OVERFLOW (expr) = TREE_CONSTANT_OVERFLOW (orig);
+	  && CONSTANT_CLASS_P (orig)
+	  && TREE_CODE (orig) != STRING_CST
+	  && (TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig)
+	      || TREE_CONSTANT_OVERFLOW (expr)
+		 != TREE_CONSTANT_OVERFLOW (orig)))
+	{
+	  if (!TREE_OVERFLOW (orig) && !TREE_CONSTANT_OVERFLOW (orig))
+	    /* Ensure constant sharing.  */
+	    expr = build_int_cst_wide (TREE_TYPE (expr),
+				       TREE_INT_CST_LOW (expr),
+				       TREE_INT_CST_HIGH (expr));
+	  else
+	    {
+	      /* Avoid clobbering a shared constant.  */
+	      expr = copy_node (expr);
+	      TREE_OVERFLOW (expr) = TREE_OVERFLOW (orig);
+	      TREE_CONSTANT_OVERFLOW (expr)
+		= TREE_CONSTANT_OVERFLOW (orig);
+	    }
 	}
       return expr;
     }
--- gcc/testsuite/g++.dg/opt/pr23056.C.jj	2005-09-05 12:57:04.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr23056.C	2005-09-05 12:56:21.000000000 +0200
@@ -0,0 +1,9 @@
+// PR c++/23056
+// { dg-do compile }
+
+template <bool T> struct S { virtual ~S(); };
+void foo ()
+{
+  static_cast<bool>("Foo");
+}
+S<true> a;

	Jakub



More information about the Gcc-patches mailing list