diff options
Diffstat (limited to 'gcc/convert.c')
-rw-r--r-- | gcc/convert.c | 135 |
1 files changed, 125 insertions, 10 deletions
diff --git a/gcc/convert.c b/gcc/convert.c index 68705f3..028497f 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "asan.h" +#include "selftest.h" #define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \ ((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR) \ @@ -98,6 +99,25 @@ convert_to_pointer_1 (tree type, tree expr, bool fold_p) } } +/* Subroutine of the various convert_to_*_maybe_fold routines. + + If a location wrapper has been folded to a constant (presumably of + a different type), re-wrap the new constant with a location wrapper. */ + +tree +preserve_any_location_wrapper (tree result, tree orig_expr) +{ + if (CONSTANT_CLASS_P (result) && location_wrapper_p (orig_expr)) + { + if (result == TREE_OPERAND (orig_expr, 0)) + return orig_expr; + else + return maybe_wrap_with_location (result, EXPR_LOCATION (orig_expr)); + } + + return result; +} + /* A wrapper around convert_to_pointer_1 that always folds the expression. */ @@ -108,12 +128,15 @@ convert_to_pointer (tree type, tree expr) } /* A wrapper around convert_to_pointer_1 that only folds the - expression if DOFOLD, or if it is CONSTANT_CLASS_P. */ + expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P. */ tree convert_to_pointer_maybe_fold (tree type, tree expr, bool dofold) { - return convert_to_pointer_1 (type, expr, dofold || CONSTANT_CLASS_P (expr)); + tree result + = convert_to_pointer_1 (type, expr, + dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr)); + return preserve_any_location_wrapper (result, expr); } /* Convert EXPR to some floating-point type TYPE. @@ -408,12 +431,15 @@ convert_to_real (tree type, tree expr) } /* A wrapper around convert_to_real_1 that only folds the - expression if DOFOLD, or if it is CONSTANT_CLASS_P. */ + expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P. */ tree convert_to_real_maybe_fold (tree type, tree expr, bool dofold) { - return convert_to_real_1 (type, expr, dofold || CONSTANT_CLASS_P (expr)); + tree result + = convert_to_real_1 (type, expr, + dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr)); + return preserve_any_location_wrapper (result, expr); } /* Try to narrow EX_FORM ARG0 ARG1 in narrowed arg types producing a @@ -679,7 +705,8 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) { case POINTER_TYPE: case REFERENCE_TYPE: - if (integer_zerop (expr) && !TREE_OVERFLOW (expr)) + if (integer_zerop (expr) + && !TREE_OVERFLOW (tree_strip_any_location_wrapper (expr))) return build_int_cst (type, 0); /* Convert to an unsigned integer of the correct width first, and from @@ -959,7 +986,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) /* When parsing long initializers, we might end up with a lot of casts. Shortcut this. */ - if (TREE_CODE (expr) == INTEGER_CST) + if (TREE_CODE (tree_strip_any_location_wrapper (expr)) == INTEGER_CST) return fold_convert (type, expr); return build1 (CONVERT_EXPR, type, expr); @@ -1017,12 +1044,15 @@ convert_to_integer (tree type, tree expr) } /* A wrapper around convert_to_complex_1 that only folds the - expression if DOFOLD, or if it is CONSTANT_CLASS_P. */ + expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P. */ tree convert_to_integer_maybe_fold (tree type, tree expr, bool dofold) { - return convert_to_integer_1 (type, expr, dofold || CONSTANT_CLASS_P (expr)); + tree result + = convert_to_integer_1 (type, expr, + dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr)); + return preserve_any_location_wrapper (result, expr); } /* Convert EXPR to the complex type TYPE in the usual ways. If FOLD_P is @@ -1101,12 +1131,15 @@ convert_to_complex (tree type, tree expr) } /* A wrapper around convert_to_complex_1 that only folds the - expression if DOFOLD, or if it is CONSTANT_CLASS_P. */ + expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P. */ tree convert_to_complex_maybe_fold (tree type, tree expr, bool dofold) { - return convert_to_complex_1 (type, expr, dofold || CONSTANT_CLASS_P (expr)); + tree result + = convert_to_complex_1 (type, expr, + dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr)); + return preserve_any_location_wrapper (result, expr); } /* Convert EXPR to the vector type TYPE in the usual ways. */ @@ -1171,3 +1204,85 @@ convert_to_fixed (tree type, tree expr) return error_mark_node; } } + +#if CHECKING_P + +namespace selftest { + +/* Selftests for conversions. */ + +static void +test_convert_to_integer_maybe_fold (tree orig_type, tree new_type) +{ + /* Calling convert_to_integer_maybe_fold on an INTEGER_CST. */ + + tree orig_cst = build_int_cst (orig_type, 42); + + /* Verify that convert_to_integer_maybe_fold on a constant returns a new + constant of the new type, unless the types are the same, in which + case verify it's a no-op. */ + { + tree result = convert_to_integer_maybe_fold (new_type, + orig_cst, false); + if (orig_type != new_type) + { + ASSERT_EQ (TREE_TYPE (result), new_type); + ASSERT_EQ (TREE_CODE (result), INTEGER_CST); + } + else + ASSERT_EQ (result, orig_cst); + } + + /* Calling convert_to_integer_maybe_fold on a location wrapper around + an INTEGER_CST. + + Verify that convert_to_integer_maybe_fold on a location wrapper + around a constant returns a new location wrapper around an equivalent + constant, both of the new type, unless the types are the same, + in which case the original wrapper should be returned. */ + { + const location_t loc = BUILTINS_LOCATION; + tree wrapped_orig_cst = maybe_wrap_with_location (orig_cst, loc); + tree result + = convert_to_integer_maybe_fold (new_type, wrapped_orig_cst, false); + ASSERT_EQ (TREE_TYPE (result), new_type); + ASSERT_EQ (EXPR_LOCATION (result), loc); + ASSERT_TRUE (location_wrapper_p (result)); + ASSERT_EQ (TREE_TYPE (TREE_OPERAND (result, 0)), new_type); + ASSERT_EQ (TREE_CODE (TREE_OPERAND (result, 0)), INTEGER_CST); + + if (orig_type == new_type) + ASSERT_EQ (result, wrapped_orig_cst); + } +} + +/* Verify that convert_to_integer_maybe_fold preserves locations. */ + +static void +test_convert_to_integer_maybe_fold () +{ + /* char -> long. */ + test_convert_to_integer_maybe_fold (char_type_node, long_integer_type_node); + + /* char -> char. */ + test_convert_to_integer_maybe_fold (char_type_node, char_type_node); + + /* long -> char. */ + test_convert_to_integer_maybe_fold (char_type_node, long_integer_type_node); + + /* long -> long. */ + test_convert_to_integer_maybe_fold (long_integer_type_node, + long_integer_type_node); +} + +/* Run all of the selftests within this file. */ + +void +convert_c_tests () +{ + test_convert_to_integer_maybe_fold (); +} + +} // namespace selftest + +#endif /* CHECKING_P */ |