Doing so allows -fanalyzer to handle std::string size() on non-empty
strings.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r17-626-g5caef7c4a904a0.
gcc/analyzer/ChangeLog:
* region-model-manager.cc
(region_model_manager::maybe_fold_binop): Fold
"(X POINTER_PLUS Y) POINTER_DIFF_EXPR X" to Y.
gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/ptr-subtraction-2.c: New test.
Signed-off-by: David Malcolm <[email protected]>
---
gcc/analyzer/region-model-manager.cc | 7 +++++
.../c-c++-common/analyzer/ptr-subtraction-2.c | 28 +++++++++++++++++++
2 files changed, 35 insertions(+)
create mode 100644 gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-2.c
diff --git a/gcc/analyzer/region-model-manager.cc
b/gcc/analyzer/region-model-manager.cc
index ba7f9db507b..4b1aacccb63 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -738,6 +738,13 @@ region_model_manager::maybe_fold_binop (tree type, enum
tree_code op,
if (binop->get_arg0 () == arg1)
return get_or_create_cast (type, binop->get_arg1 ());
break;
+ case POINTER_DIFF_EXPR:
+ /* (X POINTER_PLUS Y) POINTER_DIFF_EXPR X -> Y. */
+ if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
+ if (binop->get_op () == POINTER_PLUS_EXPR)
+ if (binop->get_arg0 () == arg1)
+ return get_or_create_cast (type, binop->get_arg1 ());
+ break;
case MULT_EXPR:
/* (VAL * 0). */
if (cst1
diff --git a/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-2.c
b/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-2.c
new file mode 100644
index 00000000000..a3c21ac54da
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-2.c
@@ -0,0 +1,28 @@
+#include "analyzer-decls.h"
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef __SIZE_TYPE__ size_t;
+
+ptrdiff_t
+ptrdiff_hidden_from_optimizer (const char *, const char *)
+ __attribute__((noinline));
+
+ptrdiff_t
+ptrdiff_hidden_from_optimizer (const char *p, const char *q)
+{
+ return p - q;
+}
+
+void
+test_concrete (void)
+{
+ const char *abc = "abc";
+ __analyzer_eval (ptrdiff_hidden_from_optimizer (abc + 3, abc) == 3); // {
dg-warning "TRUE" }
+}
+
+void
+test_symbolic (size_t sz)
+{
+ const char *abc = "abc";
+ __analyzer_eval (ptrdiff_hidden_from_optimizer (abc + sz, abc) == sz); // {
dg-warning "TRUE" }
+}
--
2.52.0