summaryrefslogtreecommitdiff
path: root/gcc/analyzer/svalue.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/svalue.cc')
-rw-r--r--gcc/analyzer/svalue.cc75
1 files changed, 68 insertions, 7 deletions
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index 553edae7250..ed289c6fc31 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -59,6 +59,8 @@ along with GCC; see the file COPYING3. If not see
namespace ana {
+static int cmp_csts_and_types (const_tree cst1, const_tree cst2);
+
/* class svalue and its various subclasses. */
/* class svalue. */
@@ -304,7 +306,7 @@ svalue::implicitly_live_p (const svalue_set *, const region_model *) const
of the same type. */
static int
-cmp_cst (const_tree cst1, const_tree cst2)
+cmp_csts_same_type (const_tree cst1, const_tree cst2)
{
gcc_assert (TREE_TYPE (cst1) == TREE_TYPE (cst2));
gcc_assert (TREE_CODE (cst1) == TREE_CODE (cst2));
@@ -323,9 +325,10 @@ cmp_cst (const_tree cst1, const_tree cst2)
TREE_REAL_CST_PTR (cst2),
sizeof (real_value));
case COMPLEX_CST:
- if (int cmp_real = cmp_cst (TREE_REALPART (cst1), TREE_REALPART (cst2)))
+ if (int cmp_real = cmp_csts_and_types (TREE_REALPART (cst1),
+ TREE_REALPART (cst2)))
return cmp_real;
- return cmp_cst (TREE_IMAGPART (cst1), TREE_IMAGPART (cst2));
+ return cmp_csts_and_types (TREE_IMAGPART (cst1), TREE_IMAGPART (cst2));
case VECTOR_CST:
if (int cmp_log2_npatterns
= ((int)VECTOR_CST_LOG2_NPATTERNS (cst1)
@@ -337,13 +340,29 @@ cmp_cst (const_tree cst1, const_tree cst2)
return cmp_nelts_per_pattern;
unsigned encoded_nelts = vector_cst_encoded_nelts (cst1);
for (unsigned i = 0; i < encoded_nelts; i++)
- if (int el_cmp = cmp_cst (VECTOR_CST_ENCODED_ELT (cst1, i),
- VECTOR_CST_ENCODED_ELT (cst2, i)))
- return el_cmp;
+ {
+ const_tree elt1 = VECTOR_CST_ENCODED_ELT (cst1, i);
+ const_tree elt2 = VECTOR_CST_ENCODED_ELT (cst2, i);
+ if (int el_cmp = cmp_csts_and_types (elt1, elt2))
+ return el_cmp;
+ }
return 0;
}
}
+/* Comparator for imposing a deterministic order on constants that might
+ not be of the same type. */
+
+static int
+cmp_csts_and_types (const_tree cst1, const_tree cst2)
+{
+ int t1 = TYPE_UID (TREE_TYPE (cst1));
+ int t2 = TYPE_UID (TREE_TYPE (cst2));
+ if (int cmp_type = t1 - t2)
+ return cmp_type;
+ return cmp_csts_same_type (cst1, cst2);
+}
+
/* Comparator for imposing a deterministic order on svalues. */
int
@@ -375,7 +394,7 @@ svalue::cmp_ptr (const svalue *sval1, const svalue *sval2)
const constant_svalue *constant_sval2 = (const constant_svalue *)sval2;
const_tree cst1 = constant_sval1->get_constant ();
const_tree cst2 = constant_sval2->get_constant ();
- return cmp_cst (cst1, cst2);
+ return cmp_csts_same_type (cst1, cst2);
}
break;
case SK_UNKNOWN:
@@ -644,6 +663,48 @@ svalue::all_zeroes_p () const
return false;
}
+/* If this svalue is a pointer, attempt to determine the base region it points
+ to. Return NULL on any problems. */
+
+const region *
+svalue::maybe_get_deref_base_region () const
+{
+ const svalue *iter = this;
+ while (1)
+ {
+ switch (iter->get_kind ())
+ {
+ default:
+ return NULL;
+
+ case SK_REGION:
+ {
+ const region_svalue *region_sval
+ = as_a <const region_svalue *> (iter);
+ return region_sval->get_pointee ()->get_base_region ();
+ }
+
+ case SK_BINOP:
+ {
+ const binop_svalue *binop_sval
+ = as_a <const binop_svalue *> (iter);
+ switch (binop_sval->get_op ())
+ {
+ case POINTER_PLUS_EXPR:
+ /* If we have a symbolic value expressing pointer arithmetic,
+ use the LHS. */
+ iter = binop_sval->get_arg0 ();
+ continue;
+
+ default:
+ return NULL;
+ }
+ return NULL;
+ }
+ }
+ }
+}
+
/* class region_svalue : public svalue. */
/* Implementation of svalue::dump_to_pp vfunc for region_svalue. */