Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r16-265-g2a63dc8c65d469.

gcc/analyzer/ChangeLog:
        PR analyzer/109366
        * region-model-manager.cc
        (region_model_manager::maybe_fold_sub_svalue): Sub-values of zero
        constants are zero.

gcc/testsuite/ChangeLog:
        PR analyzer/109366
        * g++.dg/analyzer/unique_ptr-1.C: New test.
        * g++.dg/analyzer/unique_ptr-2.C: New test.

Signed-off-by: David Malcolm <dmalc...@redhat.com>
---
 gcc/analyzer/region-model-manager.cc         |  6 ++++++
 gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C | 13 +++++++++++++
 gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C | 17 +++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C
 create mode 100644 gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C

diff --git a/gcc/analyzer/region-model-manager.cc 
b/gcc/analyzer/region-model-manager.cc
index 3e7d10485b4..df92503770b 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -944,6 +944,12 @@ region_model_manager::maybe_fold_sub_svalue (tree type,
   if (!parent_svalue->can_have_associated_state_p ())
     return get_or_create_unknown_svalue (type);
 
+  /* If we have a subvalue of a zero constant, it's zero.  */
+  if (tree cst = parent_svalue->maybe_get_constant ())
+    if (TREE_CODE (cst) == INTEGER_CST)
+      if (zerop (cst))
+       return get_or_create_cast (type, parent_svalue);
+
   /* If we have a subregion of a zero-fill, it's zero.  */
   if (const unaryop_svalue *unary
       = parent_svalue->dyn_cast_unaryop_svalue ())
diff --git a/gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C 
b/gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C
new file mode 100644
index 00000000000..cc9cf71092c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/unique_ptr-1.C
@@ -0,0 +1,13 @@
+// Verify that we complain about trivial uses of NULL unique_ptr.
+
+// { dg-do compile { target c++11 } }
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main() {
+  std::unique_ptr<A> a;
+  a->x = 12; // { dg-warning "dereference of NULL" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C 
b/gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C
new file mode 100644
index 00000000000..e8d3e7ef873
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/unique_ptr-2.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-analyzer-too-complex" } */
+
+#include <memory>
+
+struct A {int x; int y;};
+
+extern std::unique_ptr<A> make_ptr ();
+
+int test (int flag) {
+  std::unique_ptr<A> a;
+  if (flag)
+    a = make_ptr ();
+  a->x = 12; // { dg-warning "dereference of NULL" "" { xfail *-*-*} }
+  // TODO: this is failing due to "too complex" warnings
+  return 0;
+}
-- 
2.26.3

Reply via email to