diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/analyzer/region-model-manager.cc | 2 | ||||
-rw-r--r-- | gcc/analyzer/store.cc | 29 | ||||
-rw-r--r-- | gcc/analyzer/svalue.cc | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/pr94858-1.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/pr94858-2.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c | 2 |
8 files changed, 123 insertions, 4 deletions
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index ce94932..9bfb081 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -651,6 +651,8 @@ region_model_manager::get_or_create_widening_svalue (tree type, const svalue *base_sval, const svalue *iter_sval) { + gcc_assert (base_sval->get_kind () != SK_WIDENING); + gcc_assert (iter_sval->get_kind () != SK_WIDENING); widening_svalue::key_t key (type, point, base_sval, iter_sval); if (widening_svalue **slot = m_widening_values_map.get (key)) return *slot; diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 8439366..14f7c00 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -1606,6 +1606,35 @@ store::eval_alias_1 (const region *base_reg_a, /* The initial value of a pointer can't point to a local. */ return tristate::TS_FALSE; } + if (sval_a->get_kind () == SK_INITIAL + && base_reg_b->get_kind () == RK_HEAP_ALLOCATED) + { + /* The initial value of a pointer can't point to a + region that was allocated on the heap after the beginning of the + path. */ + return tristate::TS_FALSE; + } + if (const widening_svalue *widening_sval_a + = sval_a->dyn_cast_widening_svalue ()) + { + const svalue *base = widening_sval_a->get_base_svalue (); + if (const region_svalue *region_sval + = base->dyn_cast_region_svalue ()) + { + const region *pointee = region_sval->get_pointee (); + /* If we have sval_a is WIDENING(®ION, OP), and + B can't alias REGION, then B can't alias A either. + For example, A might arise from + for (ptr = ®ION; ...; ptr++) + where sval_a is ptr in the 2nd iteration of the loop. + We want to ensure that "*ptr" can only clobber things + within REGION's base region. */ + tristate ts = eval_alias (pointee->get_base_region (), + base_reg_b); + if (ts.is_false ()) + return tristate::TS_FALSE; + } + } } return tristate::TS_UNKNOWN; } diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index 99b5507..a1c6241 100644 --- a/gcc/analyzer/svalue.cc +++ b/gcc/analyzer/svalue.cc @@ -196,6 +196,18 @@ svalue::can_merge_p (const svalue *other, other, this); } + /* Merger of: + this: BINOP (X, OP, CST) + other: X, where X is non-widening + to: WIDENING (other, this). */ + if (const binop_svalue *binop_sval = dyn_cast_binop_svalue ()) + if (binop_sval->get_arg0 () == other + && binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT + && other->get_kind () != SK_WIDENING) + return mgr->get_or_create_widening_svalue (other->get_type (), + merger->m_point, + other, this); + /* Merge: (Widen(existing_val, V), existing_val) -> Widen (existing_val, V) and thus get a fixed point. */ if (const widening_svalue *widen_sval = dyn_cast_widening_svalue ()) @@ -231,6 +243,17 @@ svalue::can_merge_p (const svalue *other, { return widen_arg0; } + + /* Merger of: + this: BINOP(WIDENING(BASE, BINOP(BASE, X)), X) + other: BINOP(BASE, X) + to: WIDENING(BASE, BINOP(BASE, X)). */ + if (widen_arg0->get_iter_svalue () == other) + if (const binop_svalue *other_binop_sval + = other->dyn_cast_binop_svalue ()) + if (other_binop_sval->get_arg0 () == widen_arg0->get_base_svalue () + && other_binop_sval->get_arg1 () == binop_sval->get_arg1 ()) + return widen_arg0; } return mgr->get_or_create_unknown_svalue (get_type ()); diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c index ca6a862..5e21890 100644 --- a/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c @@ -8,8 +8,6 @@ void test(int start, int end) for (i = start; i < end; i++) { __analyzer_eval (i < end); /* { dg-warning "TRUE" "true" } */ - /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ - /* TODO(xfail^^^): should report TRUE twice. */ __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */ /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c b/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c new file mode 100644 index 0000000..f7be1c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c @@ -0,0 +1,42 @@ +#include <stdlib.h> + +typedef short hashNx; + +typedef struct hashSt { + hashNx *hs_index; + int hs_used; + int hs_slots; +} hashSt; + +void hashEmpty(hashSt *td); + +int hashAlloc(hashSt *td, int slots) { + hashNx *index; + + if (slots > td->hs_slots) { + if (td->hs_index != NULL) + index = realloc(td->hs_index, (size_t)slots * sizeof(hashNx)); + else + index = malloc((size_t)slots * sizeof(hashNx)); + + if (index == NULL) + return 0; + + td->hs_index = index; + td->hs_slots = slots; + } + + hashEmpty(td); + + return 1; +} + +void hashEmpty(hashSt *td) { + hashNx *index; + int slots; + + for (slots = td->hs_slots, index = td->hs_index; --slots >= 0;) + *index++ = -1; + + td->hs_used = 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94858-2.c b/gcc/testsuite/gcc.dg/analyzer/pr94858-2.c new file mode 100644 index 0000000..874fe8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94858-2.c @@ -0,0 +1,25 @@ +#include <stdlib.h> + +typedef short hashNx; + +typedef struct hashSt { + hashNx *hs_index; + int hs_used; + int hs_slots; +} hashSt; + +int test (hashSt *td, int slots) +{ + hashNx *index; + + index = malloc((size_t)slots * sizeof(hashNx)); + if (index == NULL) + return 0; + td->hs_index = index; + td->hs_slots = slots; + + for (slots = td->hs_slots, index = td->hs_index; --slots >= 0;) + *index++ = -1; + + return 1; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c index 95d8c53..d5b10ab 100644 --- a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c @@ -9,7 +9,7 @@ void test (int *p, int val, int count) while (n--) { - __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ *p++ = val; } diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c index 1d3576d..c3a1e11 100644 --- a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c @@ -9,7 +9,7 @@ void test (int *p, int a, int b, int count) while (n--) { - __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2|3 processed enodes" } */ *p++ = a; *p++ = b; } |