diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 8729aa8dab6273acc848179a34a430f4ee0e2e93..3f91b6107a945976e8b87e0958648dbbf9e9027d 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -2456,13 +2456,17 @@ store::eval_alias_1 (const region *base_reg_a, = base_reg_a->dyn_cast_symbolic_region ()) { const svalue *sval_a = sym_reg_a->get_pointer (); - if (sval_a->get_kind () == SK_INITIAL) - if (tree decl_b = base_reg_b->maybe_get_decl ()) - if (!is_global_var (decl_b)) - { - /* The initial value of a pointer can't point to a local. */ - return tristate::TS_FALSE; - } + if (tree decl_b = base_reg_b->maybe_get_decl ()) + { + if (!may_be_aliased (decl_b)) + return tristate::TS_FALSE; + if (sval_a->get_kind () == SK_INITIAL) + if (!is_global_var (decl_b)) + { + /* 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) { diff --git a/gcc/testsuite/gcc.dg/analyzer/aliasing-3.c b/gcc/testsuite/gcc.dg/analyzer/aliasing-3.c new file mode 100644 index 0000000000000000000000000000000000000000..003077ad5c1a7e8c30b36b79e9574df34e658753 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/aliasing-3.c @@ -0,0 +1,75 @@ +#include "analyzer-decls.h" + +#define NULL ((void *)0) + +struct s1 +{ + int f1; +}; + +static struct s1 *p1_glob = NULL; + +void test_1 (struct s1 **pp1, struct s1 *p1_parm) +{ + struct s1 *init_p1_glob = p1_glob; + + __analyzer_eval (p1_glob == init_p1_glob); /* { dg-warning "TRUE" } */ + + if (!p1_glob) + return; + + __analyzer_eval (p1_glob == init_p1_glob); /* { dg-warning "TRUE" } */ + __analyzer_eval (p1_glob != NULL); /* { dg-warning "TRUE" } */ + + *pp1 = p1_parm; + + /* The write through *pp1 can't have changed p1_glob, because + we never take a pointer to p1_glob (and it's static to this TU). */ + __analyzer_eval (p1_glob == init_p1_glob); /* { dg-warning "TRUE" } */ + __analyzer_eval (p1_glob != NULL); /* { dg-warning "TRUE" } */ +} + +struct s2 +{ + int f1; +}; + +static struct s2 *p2_glob = NULL; + +void test_2 (struct s2 **pp2, struct s2 *p2_parm) +{ + /* Ensure that p2_glob is modified. */ + p2_glob = __builtin_malloc (sizeof (struct s2)); + if (!p2_glob) + return; + + __analyzer_eval (p2_glob != NULL); /* { dg-warning "TRUE" } */ + + *pp2 = p2_parm; + + /* The write through *pp2 can't have changed p2_glob, because + we never take a pointer to p2_glob (and it's static to this TU). */ + __analyzer_eval (p2_glob != NULL); /* { dg-warning "TRUE" } */ +} + +struct s3 +{ + int f1; +}; + +struct s3 *p3_glob = NULL; + +void test_3 (struct s3 **pp3, struct s3 *p3_parm) +{ + p3_glob = __builtin_malloc (sizeof (struct s3)); + if (!p3_glob) + return; + + __analyzer_eval (p3_glob != NULL); /* { dg-warning "TRUE" } */ + + *pp3 = p3_parm; + + /* The write through *pp3 could have changed p3_glob, because + another TU could take a pointer to p3_glob. */ + __analyzer_eval (p3_glob != NULL); /* { dg-warning "UNKNOWN" } */ +}