aboutsummaryrefslogtreecommitdiff
path: root/gcc/convert.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/convert.c')
-rw-r--r--gcc/convert.c135
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 */