diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4c73cfcb72d..6e13cfd50e2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2005-09-06 Jakub Jelinek + + PR c++/23056 + * typeck.c (ignore_overflows): New helper function. + (build_static_cast_1): Use it. + 2005-09-06 Kazu Hirata * cp-tree.h, decl.c, decl2.c, semantics.c: Fix comment typos. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 96da3c636f5..d8dce75c38d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4526,6 +4526,37 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, allow_inverse_p, c_cast_p); } +/* If EXPR is an INTEGER_CST and ORIG is an arithmetic constant, return + a version of EXPR that has TREE_OVERFLOW and/or TREE_CONSTANT_OVERFLOW + set iff they are set in ORIG. Otherwise, return EXPR unchanged. */ + +static tree +ignore_overflows (tree expr, tree orig) +{ + if (TREE_CODE (expr) == INTEGER_CST + && 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; +} + /* Perform a static_cast from EXPR to TYPE. When C_CAST_P is true, this static_cast is being attempted as one of the possible casts allowed by a C-style cast. (In that case, accessibility of base @@ -4629,13 +4660,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, result = convert_from_reference (result); /* 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); - } + result = ignore_overflows (result, orig); + /* [expr.static.cast] If T is a reference type, the result is an lvalue; otherwise, @@ -4678,12 +4704,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); /* 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); - } + expr = ignore_overflows (expr, orig); return expr; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e1b8b0b21b9..760360fc9f6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2005-09-06 Jakub Jelinek + PR c++/23056 + * g++.dg/opt/pr23056.C: New test. + PR rtl-optimization/23098 * gcc.target/i386/pr23098.c: New test. diff --git a/gcc/testsuite/g++.dg/opt/pr23056.C b/gcc/testsuite/g++.dg/opt/pr23056.C new file mode 100644 index 00000000000..b9689ec5088 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr23056.C @@ -0,0 +1,9 @@ +// PR c++/23056 +// { dg-do compile } + +template struct S { virtual ~S(); }; +void foo () +{ + static_cast("Foo"); +} +S a;