From 9ef4089815fd31632557216012bd1b4d70c1cf41 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 15 May 2020 15:54:06 -0400 Subject: [PATCH 140/179] FIXME: get test_12d to work (field extraction after a struct copy) --- gcc/analyzer/region-model2.cc | 22 ++++++++++++-- gcc/analyzer/region-model2.h | 3 +- gcc/analyzer/store2.cc | 32 ++++++++++++++------ gcc/analyzer/store2.h | 5 +-- gcc/testsuite/gcc.dg/analyzer/data-model-1.c | 11 ++----- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index 17c8f9a5739..3abc494fb82 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -2871,6 +2871,23 @@ region_model2_manager::maybe_fold_sub_svalue2 (tree type, return get_or_create_cast (type, char_sval); } + /* SUB(INIT(r)).FIELD -> INIT(r.FIELD) + i.e. + Subvalue(InitialValue(R1), FieldRegion(R2, F)) + -> InitialValue(FieldRegion(R1, F)). */ + if (const initial_svalue2 *init_sval + = parent_svalue2->dyn_cast_initial_svalue2 ()) + { + if (const field_region2 *field_reg = subregion->dyn_cast_field_region2 ()) + { + const region2 *field_reg_new + = get_field_region (init_sval->get_region (), + field_reg->get_field ()); + return get_or_create_initial_value (field_reg_new); + } + } + // TODO: etc similar for element_region + return NULL; } @@ -2955,8 +2972,7 @@ region_model2_manager::get_region_for_global (tree expr, /* FIXME. */ const region2 * -region_model2_manager::get_field_region (const region2 *parent, tree field, - region_model2_context */*ctxt*/) +region_model2_manager::get_field_region (const region2 *parent, tree field) { // FIXME: should only alloc_region_id if consolidation fails region2 *field_reg = new field_region2 (alloc_region_id (), parent, field); @@ -4930,7 +4946,7 @@ region_model2::get_lvalue_1 (path_var pv, dump_location_t ()); #endif const region2 *obj_reg = get_lvalue (obj, ctxt); - return m_mgr->get_field_region (obj_reg, field, ctxt); + return m_mgr->get_field_region (obj_reg, field); } break; #if 0 diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h index 0aee4001d7e..47943b79da2 100644 --- a/gcc/analyzer/region-model2.h +++ b/gcc/analyzer/region-model2.h @@ -1579,8 +1579,7 @@ public: region_model2_context *ctxt); const decl_region2 *get_region_for_global (tree expr, region_model2_context *ctxt); - const region2 *get_field_region (const region2 *parent, tree field, - region_model2_context *ctxt); + const region2 *get_field_region (const region2 *parent, tree field); const region2 *get_element_region (const region2 *parent, tree element_type, const svalue2 *index, diff --git a/gcc/analyzer/store2.cc b/gcc/analyzer/store2.cc index c588edc40f9..a8d3973644f 100644 --- a/gcc/analyzer/store2.cc +++ b/gcc/analyzer/store2.cc @@ -409,21 +409,21 @@ binding_cluster2::get_binding (store2_manager *mgr, /* FIXME. */ const svalue2 * -binding_cluster2::get_default_binding_recursive (store2_manager *mgr, - const region2 *reg) const +binding_cluster2::get_binding_recursive (store2_manager *mgr, + const region2 *reg, + enum binding_kind kind) const { - if (const svalue2 *default_sval - = get_binding (mgr, reg, BK_default)) - return default_sval; + if (const svalue2 *sval = get_binding (mgr, reg, kind)) + return sval; if (reg != m_base_region) if (const region2 *parent_reg = reg->get_parent_region ()) - if (const svalue2 *parent_default_sval - = get_default_binding_recursive (mgr, parent_reg)) + if (const svalue2 *parent_sval + = get_binding_recursive (mgr, parent_reg, kind)) { /* Extract child svalue from parent svalue. */ region_model2_manager *rmm_mgr = mgr->get_svalue2_manager (); return rmm_mgr->get_or_create_sub_svalue2 (reg->get_type (), - parent_default_sval, reg); + parent_sval, reg); } return NULL; } @@ -434,10 +434,22 @@ const svalue2 * binding_cluster2::get_any_binding (store2_manager *mgr, const region2 *reg) const { + /* FIXME: I'm not quite sure how this should work. + This looks recursively for matches for a "direct" binding, + then for a "default" binding. + Doing so gets data-model-1.c: test_12d to work, where we + can extract the initial_value of a different struct, then + get a field of it. + But when should bindings be default, and when should they be direct? + The code uses "default" for things that are typically a parent + region, and "direct" elsewhere. */ if (const svalue2 *direct_sval - = get_binding (mgr, reg, BK_direct)) + = get_binding_recursive (mgr, reg, BK_direct)) return direct_sval; - return get_default_binding_recursive (mgr, reg); + if (const svalue2 *default_sval + = get_binding_recursive (mgr, reg, BK_default)) + return default_sval; + return NULL; } /* Populate OUT with all bindings within this cluster that overlap REG. */ diff --git a/gcc/analyzer/store2.h b/gcc/analyzer/store2.h index 43d148318b6..216f2da9254 100644 --- a/gcc/analyzer/store2.h +++ b/gcc/analyzer/store2.h @@ -205,8 +205,9 @@ public: const svalue2 *get_binding (store2_manager *mgr, const region2 *reg, binding_kind kind) const; - const svalue2 *get_default_binding_recursive (store2_manager *mgr, - const region2 *reg) const; + const svalue2 *get_binding_recursive (store2_manager *mgr, + const region2 *reg, + enum binding_kind kind) const; const svalue2 *get_any_binding (store2_manager *mgr, const region2 *reg) const; diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c index 47423c3d742..c368ba20e25 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c @@ -179,15 +179,8 @@ int test_12d (struct coord c) { struct coord d; d = c; - __analyzer_eval (d.x == c.x); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "actual" { target *-*-* } .-1 } */ - /* TODO(xfail): c and d share the same unknown value of type "coord", but - attempts to access the fields lead to different unknown values. */ - - __analyzer_eval (d.y == c.y); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "actual" { target *-*-* } .-1 } */ - // TODO(xfail): likewise - + __analyzer_eval (d.x == c.x); /* { dg-warning "TRUE" } */ + __analyzer_eval (d.y == c.y); /* { dg-warning "TRUE" } */ __analyzer_eval (d.x == d.y); /* { dg-warning "UNKNOWN" } */ /* d and c share an unknown value of type "struct coord". But d.x and d.y should be different unknown values (although they inherit -- 2.21.0