aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-02-05 12:09:23 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2020-02-06 14:44:23 -0500
commitcb273d81a45092ceee793f0357526e291f03c7b7 (patch)
treeec55943171813f6aee0f75f7a08d3a5a74ec5783 /gcc
parent1ccdd460d1033f7e9158b1c6adfe208f315d1300 (diff)
downloadgcc-cb273d81a45092ceee793f0357526e291f03c7b7.zip
gcc-cb273d81a45092ceee793f0357526e291f03c7b7.tar.gz
gcc-cb273d81a45092ceee793f0357526e291f03c7b7.tar.bz2
analyzer: round-trip pointer-equality through intptr_t
When investigating how the analyzer handles malloc/free of Cray pointers in gfortran I noticed that that analyzer was losing information on pointers that were cast to an integer type, and then back to a pointer type again. The root cause is that region_model::maybe_cast_1 was only preserving the region_svalue-ness of the result if both types were pointers, instead returning an unknown_svalue for a pointer-to-int cast. This patch updates the above code so that it attempts to use a region_svalue if *either* type is a pointer Doing so allows the analyzer to recognize that the same underlying region is in use through various casts through integer types. gcc/analyzer/ChangeLog: * region-model.cc (region_model::maybe_cast_1): Attempt to provide a region_svalue if either type is a pointer, rather than if both types are pointers. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/torture/intptr_t.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/ChangeLog6
-rw-r--r--gcc/analyzer/region-model.cc2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c28
4 files changed, 39 insertions, 1 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 0666d00..ba59131 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-06 David Malcolm <dmalcolm@redhat.com>
+
+ * region-model.cc (region_model::maybe_cast_1): Attempt to provide
+ a region_svalue if either type is a pointer, rather than if both
+ types are pointers.
+
2020-02-05 David Malcolm <dmalcolm@redhat.com>
* engine.cc (exploded_node::dump_dot): Show merger enodes.
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c837ec6..60363c7 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -4977,7 +4977,7 @@ region_model::maybe_cast_1 (tree dst_type, svalue_id sid)
return sid;
if (POINTER_TYPE_P (dst_type)
- && POINTER_TYPE_P (src_type))
+ || POINTER_TYPE_P (src_type))
{
/* Pointer to region. */
if (region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fd80c8d..f6f12dd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2020-02-06 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/analyzer/torture/intptr_t.c: New test.
+
2020-02-06 Segher Boessenkool <segher@kernel.crashing.org>
* gcc.target/powerpc/pr93012.c: New.
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c b/gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c
new file mode 100644
index 0000000..847ba62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c
@@ -0,0 +1,28 @@
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+#include <stdlib.h>
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+void test_1 (void)
+{
+ intptr_t ip;
+ void *p = malloc (1024);
+ ip = (intptr_t)p;
+ free ((void *)ip);
+} /* { dg-bogus "leak" } */
+
+void test_2 (void)
+{
+ uintptr_t uip;
+ void *p = malloc (1024);
+ uip = (uintptr_t)p;
+ free ((void *)uip);
+} /* { dg-bogus "leak" } */
+
+void test_3 (intptr_t ip)
+{
+ free ((void *)ip); /* { dg-message "first 'free'" } */
+ free ((void *)ip); /* { dg-warning "double-'free'" } */
+}