aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/analyzer/ChangeLog16
-rw-r--r--gcc/analyzer/region-model.cc71
-rw-r--r--gcc/analyzer/region-model.h8
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/expect-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-4.c20
-rw-r--r--gcc/testsuite/gfortran.dg/analyzer/pr93993.f906
7 files changed, 152 insertions, 9 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 4f3e08e4dc4..c4724cb090d 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,6 +1,22 @@
2020-03-04 David Malcolm <dmalcolm@redhat.com>
PR analyzer/93993
+ * region-model.cc (region_model::on_call_pre): Handle
+ BUILT_IN_EXPECT and its variants.
+ (region_model::add_any_constraints_from_ssa_def_stmt): Split out
+ gassign handling into add_any_constraints_from_gassign; add gcall
+ handling.
+ (region_model::add_any_constraints_from_gassign): New function,
+ based on the above. Add handling for NOP_EXPR.
+ (region_model::add_any_constraints_from_gcall): New function.
+ (region_model::get_representative_path_var): Handle views.
+ * region-model.h
+ (region_model::add_any_constraints_from_ssa_def_stmt): New decl.
+ (region_model::add_any_constraints_from_gassign): New decl.
+
+2020-03-04 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/93993
* checker-path.h (state_change_event::get_lvalue): Add ctxt param
and pass it to region_model::get_value call.
* diagnostic-manager.cc (get_any_origin): Pass a
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index b2179bd220a..6813117968f 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -4204,6 +4204,19 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt)
}
return false;
}
+ else if (gimple_call_builtin_p (call, BUILT_IN_EXPECT)
+ || gimple_call_builtin_p (call, BUILT_IN_EXPECT_WITH_PROBABILITY)
+ || gimple_call_internal_p (call, IFN_BUILTIN_EXPECT))
+ {
+ /* __builtin_expect's return value is its initial argument. */
+ if (!lhs_rid.null_p ())
+ {
+ tree initial_arg = gimple_call_arg (call, 0);
+ svalue_id sid = get_rvalue (initial_arg, ctxt);
+ set_value (lhs_rid, sid, ctxt);
+ }
+ return false;
+ }
else if (is_named_call_p (callee_fndecl, "strlen", call, 1))
{
region_id buf_rid = deref_rvalue (gimple_call_arg (call, 0), ctxt);
@@ -5447,28 +5460,46 @@ region_model::add_any_constraints_from_ssa_def_stmt (tree lhs,
if (TREE_CODE (lhs) != SSA_NAME)
return;
- if (rhs != boolean_false_node)
+ if (!zerop (rhs))
return;
if (op != NE_EXPR && op != EQ_EXPR)
return;
+ gimple *def_stmt = SSA_NAME_DEF_STMT (lhs);
+ if (const gassign *assign = dyn_cast<gassign *> (def_stmt))
+ add_any_constraints_from_gassign (op, rhs, assign, ctxt);
+ else if (gcall *call = dyn_cast<gcall *> (def_stmt))
+ add_any_constraints_from_gcall (op, rhs, call, ctxt);
+}
+
+/* Add any constraints for an SSA_NAME defined by ASSIGN
+ where the result OP RHS. */
+
+void
+region_model::add_any_constraints_from_gassign (enum tree_code op,
+ tree rhs,
+ const gassign *assign,
+ region_model_context *ctxt)
+{
/* We have either
- "LHS != false" (i.e. LHS is true), or
- "LHS == false" (i.e. LHS is false). */
bool is_true = op == NE_EXPR;
- gimple *def_stmt = SSA_NAME_DEF_STMT (lhs);
- gassign *assign = dyn_cast<gassign *> (def_stmt);
- if (!assign)
- return;
-
enum tree_code rhs_code = gimple_assign_rhs_code (assign);
switch (rhs_code)
{
default:
break;
+
+ case NOP_EXPR:
+ {
+ add_constraint (gimple_assign_rhs1 (assign), op, rhs, ctxt);
+ }
+ break;
+
case BIT_AND_EXPR:
{
if (is_true)
@@ -5514,6 +5545,24 @@ region_model::add_any_constraints_from_ssa_def_stmt (tree lhs,
}
}
+/* Add any constraints for an SSA_NAME defined by CALL
+ where the result OP RHS. */
+
+void
+region_model::add_any_constraints_from_gcall (enum tree_code op,
+ tree rhs,
+ const gcall *call,
+ region_model_context *ctxt)
+{
+ if (gimple_call_builtin_p (call, BUILT_IN_EXPECT)
+ || gimple_call_builtin_p (call, BUILT_IN_EXPECT_WITH_PROBABILITY)
+ || gimple_call_internal_p (call, IFN_BUILTIN_EXPECT))
+ {
+ /* __builtin_expect's return value is its initial argument. */
+ add_constraint (gimple_call_arg (call, 0), op, rhs, ctxt);
+ }
+}
+
/* Determine what is known about the condition "LHS OP RHS" within
this model.
Use CTXT for reporting any diagnostics associated with the accesses. */
@@ -5608,6 +5657,16 @@ region_model::get_representative_path_var (region_id rid) const
region *parent_reg = get_region (parent_rid);
if (parent_reg)
{
+ if (reg->is_view_p ())
+ {
+ path_var parent_pv = get_representative_path_var (parent_rid);
+ if (parent_pv.m_tree && reg->get_type ())
+ return path_var (build1 (NOP_EXPR,
+ TREE_TYPE (reg->get_type ()),
+ parent_pv.m_tree),
+ parent_pv.m_stack_depth);
+ }
+
if (parent_reg->get_kind () == RK_STRUCT)
{
map_region *parent_map_region = (map_region *)parent_reg;
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index f3cf45566d1..6d49f00cfe3 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -1850,6 +1850,14 @@ class region_model
enum tree_code op,
tree rhs,
region_model_context *ctxt);
+ void add_any_constraints_from_gassign (enum tree_code op,
+ tree rhs,
+ const gassign *assign,
+ region_model_context *ctxt);
+ void add_any_constraints_from_gcall (enum tree_code op,
+ tree rhs,
+ const gcall *call,
+ region_model_context *ctxt);
void update_for_call_superedge (const call_superedge &call_edge,
region_model_context *ctxt);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d44d3c7cbe5..af4470d6303 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,14 @@
2020-03-04 David Malcolm <dmalcolm@redhat.com>
PR analyzer/93993
+ * gcc.dg/analyzer/expect-1.c: New test.
+ * gcc.dg/analyzer/malloc-4.c: New test.
+ * gfortran.dg/analyzer/pr93993.f90: Remove xfail from dg-bogus.
+ Move location of leak warning and update message.
+
+2020-03-04 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/93993
* gfortran.dg/analyzer/pr93993.f90: New test.
2020-03-04 Martin Liska <mliska@suse.cz>
diff --git a/gcc/testsuite/gcc.dg/analyzer/expect-1.c b/gcc/testsuite/gcc.dg/analyzer/expect-1.c
new file mode 100644
index 00000000000..e538f77741d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/expect-1.c
@@ -0,0 +1,32 @@
+#define NULL ((void*)0)
+
+void *test_1 (void)
+{
+ int *p = (int *)__builtin_malloc (sizeof (int));
+ if (__builtin_expect (p != NULL, 1))
+ {
+ *p = 42;
+ return p;
+ }
+ return NULL;
+}
+
+void *test_2 (void)
+{
+ int *p = (int *)__builtin_malloc (sizeof (int));
+ if (__builtin_expect (p == NULL, 1))
+ return NULL;
+
+ *p = 42;
+ return p;
+}
+
+void *test_3 (void)
+{
+ int *p = (int *)__builtin_malloc (sizeof (int));
+ if (__builtin_expect_with_probability (p == NULL, 1, 0.5f))
+ return NULL;
+
+ *p = 42;
+ return p;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-4.c b/gcc/testsuite/gcc.dg/analyzer/malloc-4.c
new file mode 100644
index 00000000000..94d2825a33e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-4.c
@@ -0,0 +1,20 @@
+/* { dg-additional-options "-Wno-incompatible-pointer-types" } */
+
+#include <stdlib.h>
+
+struct foo;
+struct bar;
+void *hv (struct foo **tm)
+{
+ void *p = __builtin_malloc (4);
+ *tm = p;
+ if (!p)
+ abort ();
+ return p; /* { dg-warning "leak of 'tm'" } */
+}
+
+void a5 (void)
+{
+ struct bar *qb = NULL;
+ hv (&qb);
+} /* { dg-warning "leak of '\\(struct foo\\)qb'" } */
diff --git a/gcc/testsuite/gfortran.dg/analyzer/pr93993.f90 b/gcc/testsuite/gfortran.dg/analyzer/pr93993.f90
index 8d5261c0eb9..230b99e4fcd 100644
--- a/gcc/testsuite/gfortran.dg/analyzer/pr93993.f90
+++ b/gcc/testsuite/gfortran.dg/analyzer/pr93993.f90
@@ -16,9 +16,9 @@ contains
type (et(real_kind=za)), allocatable, target :: tm
type (et(real_kind=za)), pointer :: ce
- allocate (tm) ! { dg-bogus "dereference of possibly-NULL" "" { xfail *-*-* } }
+ allocate (tm) ! { dg-bogus "dereference of possibly-NULL" }
ce => tm
- end function hv ! { dg-warning "leak of 'tm'" }
+ end function hv
end module gg
@@ -30,4 +30,4 @@ program a5
type (et(real_kind=za)), pointer :: vt
vt => hv (qb)
-end program a5
+end program a5 ! { dg-warning "leak of '.*qb'" }