[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