diff options
Diffstat (limited to 'gcc/analyzer/svalue.cc')
-rw-r--r-- | gcc/analyzer/svalue.cc | 75 |
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. */ |