diff options
author | David Malcolm <dmalcolm@redhat.com> | 2022-12-01 21:28:55 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2022-12-01 21:28:55 -0500 |
commit | 0b737090a69624dea5318c380620283f0321a92e (patch) | |
tree | 1819faafd6a9e0b3e79c6028385bfa1c11efd738 /gcc | |
parent | 5cb7d28dcfb11a2810db55b0bbd71fe562bdc2a3 (diff) | |
download | gcc-0b737090a69624dea5318c380620283f0321a92e.zip gcc-0b737090a69624dea5318c380620283f0321a92e.tar.gz gcc-0b737090a69624dea5318c380620283f0321a92e.tar.bz2 |
analyzer: handle comparisons against negated symbolic values [PR107948]
gcc/analyzer/ChangeLog:
PR analyzer/107948
* region-model-manager.cc
(region_model_manager::maybe_fold_binop): Fold (0 - VAL) to -VAL.
* region-model.cc (region_model::eval_condition): Handle e.g.
"-X <= 0" as equivalent to X >= 0".
gcc/testsuite/ChangeLog:
PR analyzer/107948
* gcc.dg/analyzer/feasibility-pr107948.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/analyzer/region-model-manager.cc | 3 | ||||
-rw-r--r-- | gcc/analyzer/region-model.cc | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/feasibility-pr107948.c | 49 |
3 files changed, 65 insertions, 0 deletions
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index ae63c66..471a927 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -620,6 +620,9 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op, /* (VAL - 0) -> VAL. */ if (cst1 && zerop (cst1)) return get_or_create_cast (type, arg0); + /* (0 - VAL) -> -VAL. */ + if (cst0 && zerop (cst0)) + return get_or_create_unaryop (type, NEGATE_EXPR, arg1); break; case MULT_EXPR: /* (VAL * 0). */ diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 91b868f..4f623fd 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -3339,6 +3339,19 @@ region_model::eval_condition (const svalue *lhs, return lhs_ts; } } + else if (const unaryop_svalue *unaryop + = lhs->dyn_cast_unaryop_svalue ()) + { + if (unaryop->get_op () == NEGATE_EXPR) + { + /* e.g. "-X <= 0" is equivalent to X >= 0". */ + tristate lhs_ts = eval_condition (unaryop->get_arg (), + swap_tree_comparison (op), + rhs); + if (lhs_ts.is_known ()) + return lhs_ts; + } + } } /* Handle rejection of equality for comparisons of the initial values of diff --git a/gcc/testsuite/gcc.dg/analyzer/feasibility-pr107948.c b/gcc/testsuite/gcc.dg/analyzer/feasibility-pr107948.c new file mode 100644 index 0000000..5eb8b0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/feasibility-pr107948.c @@ -0,0 +1,49 @@ +#include "analyzer-decls.h" + +void foo(int width) { + int i = 0; + int base; + if (width > 0){ + __analyzer_eval(i == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(width > 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(width - i > 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(i - width <= 0); /* { dg-warning "TRUE" } */ + if (i - width <= 0) { + base = 512; + } + else { + __analyzer_dump_path (); /* { dg-bogus "path" } */ + } + base+=1; /* { dg-bogus "uninit" } */ + } +} + +void test_ge_zero (int x) +{ + if (x >= 0) + { + __analyzer_eval(x >= 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(x > 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval(x <= 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval(x < 0); /* { dg-warning "FALSE" } */ + __analyzer_eval(-x <= 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(-x < 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval(-x >= 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval(-x > 0); /* { dg-warning "FALSE" } */ + } +} + +void test_gt_zero (int x) +{ + if (x > 0) + { + __analyzer_eval(x >= 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(x > 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(x <= 0); /* { dg-warning "FALSE" } */ + __analyzer_eval(x < 0); /* { dg-warning "FALSE" } */ + __analyzer_eval(-x <= 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(-x < 0); /* { dg-warning "TRUE" } */ + __analyzer_eval(-x >= 0); /* { dg-warning "FALSE" } */ + __analyzer_eval(-x > 0); /* { dg-warning "FALSE" } */ + } +} |