aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/region-model-manager.cc2
-rw-r--r--gcc/analyzer/store.cc29
-rw-r--r--gcc/analyzer/svalue.cc23
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr94858-1.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr94858-2.c25
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c2
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(&REGION, OP), and
+ B can't alias REGION, then B can't alias A either.
+ For example, A might arise from
+ for (ptr = &REGION; ...; 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;
}