mirror of git://gcc.gnu.org/git/gcc.git
re PR c/16351 (NULL dereference warnings)
gcc/ChangeLog: 2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org> Jeff Law <law@redhat.com> PR c/16351 * doc/invoke.texi (Wnull-dereference): New. * tree-vrp.c (infer_value_range): Update call to infer_nonnull_range. * gimple-ssa-isolate-paths.c (find_implicit_erroneous_behaviour): Warn for potential NULL dereferences. (find_explicit_erroneous_behaviour): Warn for NULL dereferences. * ubsan.c (instrument_nonnull_arg): Call infer_nonnull_range_by_attribute. (instrument_nonnull_return): Likewise. * common.opt (Wnull-dereference); New. * gimple.c (infer_nonnull_range): Remove bool arguments. (infer_nonnull_range_by_dereference): New. (infer_nonnull_range_by_attribute): New. * gimple.h: Update declarations. gcc/testsuite/ChangeLog: 2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org> Jeff Law <law@redhat.com> PR c/16351 * gcc.dg/tree-ssa/isolate-2.c: Close comment. * gcc.dg/tree-ssa/isolate-4.c: Likewise. * gcc.dg/tree-ssa/wnull-dereference.c: New test. * gcc.dg/tree-ssa/isolate-1.c: Test warnings with -Wnull-dereference. * gcc.dg/tree-ssa/isolate-3.c: Likewise. * gcc.dg/tree-ssa/isolate-5.c: Likewise. Co-Authored-By: Jeff Law <law@redhat.com> From-SVN: r226640
This commit is contained in:
parent
72a35f9354
commit
76787f7009
|
|
@ -1,3 +1,21 @@
|
||||||
|
2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org>
|
||||||
|
Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
PR c/16351
|
||||||
|
* doc/invoke.texi (Wnull-dereference): New.
|
||||||
|
* tree-vrp.c (infer_value_range): Update call to infer_nonnull_range.
|
||||||
|
* gimple-ssa-isolate-paths.c (find_implicit_erroneous_behaviour):
|
||||||
|
Warn for potential NULL dereferences.
|
||||||
|
(find_explicit_erroneous_behaviour): Warn for NULL dereferences.
|
||||||
|
* ubsan.c (instrument_nonnull_arg): Call
|
||||||
|
infer_nonnull_range_by_attribute.
|
||||||
|
(instrument_nonnull_return): Likewise.
|
||||||
|
* common.opt (Wnull-dereference); New.
|
||||||
|
* gimple.c (infer_nonnull_range): Remove bool arguments.
|
||||||
|
(infer_nonnull_range_by_dereference): New.
|
||||||
|
(infer_nonnull_range_by_attribute): New.
|
||||||
|
* gimple.h: Update declarations.
|
||||||
|
|
||||||
2015-08-05 Richard Sandiford <richard.sandiford@arm.com>
|
2015-08-05 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
* gensupport.c (sequence_num): Replace with...
|
* gensupport.c (sequence_num): Replace with...
|
||||||
|
|
|
||||||
|
|
@ -592,6 +592,10 @@ Wlarger-than=
|
||||||
Common RejectNegative Joined UInteger Warning
|
Common RejectNegative Joined UInteger Warning
|
||||||
-Wlarger-than=<number> Warn if an object is larger than <number> bytes
|
-Wlarger-than=<number> Warn if an object is larger than <number> bytes
|
||||||
|
|
||||||
|
Wnull-dereference
|
||||||
|
Common Var(warn_null_dereference) Warning EnabledBy(Wall)
|
||||||
|
Warn if dereferencing a NULL pointer may lead to erroneous or undefined behavior
|
||||||
|
|
||||||
Wunsafe-loop-optimizations
|
Wunsafe-loop-optimizations
|
||||||
Common Var(warn_unsafe_loop_optimizations) Warning
|
Common Var(warn_unsafe_loop_optimizations) Warning
|
||||||
Warn if the loop cannot be optimized due to nontrivial assumptions.
|
Warn if the loop cannot be optimized due to nontrivial assumptions.
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||||
-Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol
|
-Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol
|
||||||
-Winit-self -Winline -Wno-int-conversion @gol
|
-Winit-self -Winline -Wno-int-conversion @gol
|
||||||
-Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol
|
-Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol
|
||||||
|
-Wnull-dereference @gol
|
||||||
-Winvalid-pch -Wlarger-than=@var{len} -Wunsafe-loop-optimizations @gol
|
-Winvalid-pch -Wlarger-than=@var{len} -Wunsafe-loop-optimizations @gol
|
||||||
-Wlogical-op -Wlogical-not-parentheses -Wlong-long @gol
|
-Wlogical-op -Wlogical-not-parentheses -Wlong-long @gol
|
||||||
-Wmain -Wmaybe-uninitialized -Wmemset-transposed-args @gol
|
-Wmain -Wmaybe-uninitialized -Wmemset-transposed-args @gol
|
||||||
|
|
@ -4156,6 +4157,16 @@ In order to get a warning about an unused function parameter, you must
|
||||||
either specify @option{-Wextra -Wunused} (note that @option{-Wall} implies
|
either specify @option{-Wextra -Wunused} (note that @option{-Wall} implies
|
||||||
@option{-Wunused}), or separately specify @option{-Wunused-parameter}.
|
@option{-Wunused}), or separately specify @option{-Wunused-parameter}.
|
||||||
|
|
||||||
|
@item -Wnull-dereference
|
||||||
|
@opindex Wnull-dereference
|
||||||
|
@opindex Wno-null-dereference
|
||||||
|
Warn if the compiler detects paths that trigger erroneous or
|
||||||
|
undefined behavior due to dereferencing a null pointer. This option
|
||||||
|
is only active when @option{-fdelete-null-pointer-checks} is active,
|
||||||
|
which is enabled by optimizations in most targets. The precision of
|
||||||
|
the warnings depends on the optimization options used. This option is
|
||||||
|
enabled by @option{-Wall}.
|
||||||
|
|
||||||
@item -Wuninitialized
|
@item -Wuninitialized
|
||||||
@opindex Wuninitialized
|
@opindex Wuninitialized
|
||||||
@opindex Wno-uninitialized
|
@opindex Wno-uninitialized
|
||||||
|
|
|
||||||
|
|
@ -331,11 +331,29 @@ find_implicit_erroneous_behaviour (void)
|
||||||
if (gimple_bb (use_stmt) != bb)
|
if (gimple_bb (use_stmt) != bb)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (infer_nonnull_range (use_stmt, lhs,
|
bool by_dereference
|
||||||
flag_isolate_erroneous_paths_dereference,
|
= infer_nonnull_range_by_dereference (use_stmt, lhs);
|
||||||
flag_isolate_erroneous_paths_attribute))
|
|
||||||
|
|
||||||
|
if (by_dereference
|
||||||
|
|| infer_nonnull_range_by_attribute (use_stmt, lhs))
|
||||||
{
|
{
|
||||||
|
location_t loc = gimple_location (use_stmt)
|
||||||
|
? gimple_location (use_stmt)
|
||||||
|
: gimple_phi_arg_location (phi, i);
|
||||||
|
|
||||||
|
if (by_dereference)
|
||||||
|
{
|
||||||
|
warning_at (loc, OPT_Wnull_dereference,
|
||||||
|
"potential null pointer dereference");
|
||||||
|
if (!flag_isolate_erroneous_paths_dereference)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!flag_isolate_erroneous_paths_attribute)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
duplicate = isolate_path (bb, duplicate, e,
|
duplicate = isolate_path (bb, duplicate, e,
|
||||||
use_stmt, lhs, false);
|
use_stmt, lhs, false);
|
||||||
|
|
||||||
|
|
@ -381,13 +399,29 @@ find_explicit_erroneous_behaviour (void)
|
||||||
{
|
{
|
||||||
gimple stmt = gsi_stmt (si);
|
gimple stmt = gsi_stmt (si);
|
||||||
|
|
||||||
/* By passing null_pointer_node, we can use infer_nonnull_range
|
/* By passing null_pointer_node, we can use the
|
||||||
to detect explicit NULL pointer dereferences and other uses
|
infer_nonnull_range functions to detect explicit NULL
|
||||||
where a non-NULL value is required. */
|
pointer dereferences and other uses where a non-NULL
|
||||||
if (infer_nonnull_range (stmt, null_pointer_node,
|
value is required. */
|
||||||
flag_isolate_erroneous_paths_dereference,
|
|
||||||
flag_isolate_erroneous_paths_attribute))
|
bool by_dereference
|
||||||
|
= infer_nonnull_range_by_dereference (stmt, null_pointer_node);
|
||||||
|
if (by_dereference
|
||||||
|
|| infer_nonnull_range_by_attribute (stmt, null_pointer_node))
|
||||||
{
|
{
|
||||||
|
if (by_dereference)
|
||||||
|
{
|
||||||
|
warning_at (gimple_location (stmt), OPT_Wnull_dereference,
|
||||||
|
"null pointer dereference");
|
||||||
|
if (!flag_isolate_erroneous_paths_dereference)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!flag_isolate_erroneous_paths_attribute)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
insert_trap_and_remove_trailing_statements (&si,
|
insert_trap_and_remove_trailing_statements (&si,
|
||||||
null_pointer_node);
|
null_pointer_node);
|
||||||
|
|
||||||
|
|
@ -534,7 +568,8 @@ public:
|
||||||
/* If we do not have a suitable builtin function for the trap statement,
|
/* If we do not have a suitable builtin function for the trap statement,
|
||||||
then do not perform the optimization. */
|
then do not perform the optimization. */
|
||||||
return (flag_isolate_erroneous_paths_dereference != 0
|
return (flag_isolate_erroneous_paths_dereference != 0
|
||||||
|| flag_isolate_erroneous_paths_attribute != 0);
|
|| flag_isolate_erroneous_paths_attribute != 0
|
||||||
|
|| warn_null_dereference);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned int execute (function *)
|
virtual unsigned int execute (function *)
|
||||||
|
|
|
||||||
42
gcc/gimple.c
42
gcc/gimple.c
|
|
@ -2618,16 +2618,20 @@ check_loadstore (gimple, tree op, tree, void *data)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If OP can be inferred to be non-NULL after STMT executes, return true.
|
|
||||||
|
|
||||||
DEREFERENCE is TRUE if we can use a pointer dereference to infer a
|
|
||||||
non-NULL range, FALSE otherwise.
|
|
||||||
|
|
||||||
ATTRIBUTE is TRUE if we can use attributes to infer a non-NULL range
|
|
||||||
for function arguments and return values. FALSE otherwise. */
|
|
||||||
|
|
||||||
|
/* Return true if OP can be inferred to be non-NULL after STMT executes,
|
||||||
|
either by using a pointer dereference or attributes. */
|
||||||
bool
|
bool
|
||||||
infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
|
infer_nonnull_range (gimple stmt, tree op)
|
||||||
|
{
|
||||||
|
return infer_nonnull_range_by_dereference (stmt, op)
|
||||||
|
|| infer_nonnull_range_by_attribute (stmt, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if OP can be inferred to be non-NULL after STMT
|
||||||
|
executes by using a pointer dereference. */
|
||||||
|
bool
|
||||||
|
infer_nonnull_range_by_dereference (gimple stmt, tree op)
|
||||||
{
|
{
|
||||||
/* We can only assume that a pointer dereference will yield
|
/* We can only assume that a pointer dereference will yield
|
||||||
non-NULL if -fdelete-null-pointer-checks is enabled. */
|
non-NULL if -fdelete-null-pointer-checks is enabled. */
|
||||||
|
|
@ -2636,13 +2640,26 @@ infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
|
||||||
|| gimple_code (stmt) == GIMPLE_ASM)
|
|| gimple_code (stmt) == GIMPLE_ASM)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (dereference
|
if (walk_stmt_load_store_ops (stmt, (void *)op,
|
||||||
&& walk_stmt_load_store_ops (stmt, (void *)op,
|
|
||||||
check_loadstore, check_loadstore))
|
check_loadstore, check_loadstore))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (attribute
|
return false;
|
||||||
&& is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
|
}
|
||||||
|
|
||||||
|
/* Return true if OP can be inferred to be a non-NULL after STMT
|
||||||
|
executes by using attributes. */
|
||||||
|
bool
|
||||||
|
infer_nonnull_range_by_attribute (gimple stmt, tree op)
|
||||||
|
{
|
||||||
|
/* We can only assume that a pointer dereference will yield
|
||||||
|
non-NULL if -fdelete-null-pointer-checks is enabled. */
|
||||||
|
if (!flag_delete_null_pointer_checks
|
||||||
|
|| !POINTER_TYPE_P (TREE_TYPE (op))
|
||||||
|
|| gimple_code (stmt) == GIMPLE_ASM)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
|
||||||
{
|
{
|
||||||
tree fntype = gimple_call_fntype (stmt);
|
tree fntype = gimple_call_fntype (stmt);
|
||||||
tree attrs = TYPE_ATTRIBUTES (fntype);
|
tree attrs = TYPE_ATTRIBUTES (fntype);
|
||||||
|
|
@ -2681,7 +2698,6 @@ infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
|
||||||
|
|
||||||
/* If this function is marked as returning non-null, then we can
|
/* If this function is marked as returning non-null, then we can
|
||||||
infer OP is non-null if it is used in the return statement. */
|
infer OP is non-null if it is used in the return statement. */
|
||||||
if (attribute)
|
|
||||||
if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
|
if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
|
||||||
if (gimple_return_retval (return_stmt)
|
if (gimple_return_retval (return_stmt)
|
||||||
&& operand_equal_p (gimple_return_retval (return_stmt), op, 0)
|
&& operand_equal_p (gimple_return_retval (return_stmt), op, 0)
|
||||||
|
|
|
||||||
|
|
@ -1401,7 +1401,9 @@ extern bool gimple_call_builtin_p (const_gimple, enum built_in_function);
|
||||||
extern bool gimple_asm_clobbers_memory_p (const gasm *);
|
extern bool gimple_asm_clobbers_memory_p (const gasm *);
|
||||||
extern void dump_decl_set (FILE *, bitmap);
|
extern void dump_decl_set (FILE *, bitmap);
|
||||||
extern bool nonfreeing_call_p (gimple);
|
extern bool nonfreeing_call_p (gimple);
|
||||||
extern bool infer_nonnull_range (gimple, tree, bool, bool);
|
extern bool infer_nonnull_range (gimple, tree);
|
||||||
|
extern bool infer_nonnull_range_by_dereference (gimple, tree);
|
||||||
|
extern bool infer_nonnull_range_by_attribute (gimple, tree);
|
||||||
extern void sort_case_labels (vec<tree>);
|
extern void sort_case_labels (vec<tree>);
|
||||||
extern void preprocess_case_label_vec_for_gimple (vec<tree>, tree, tree *);
|
extern void preprocess_case_label_vec_for_gimple (vec<tree>, tree, tree *);
|
||||||
extern void gimple_seq_set_location (gimple_seq, location_t);
|
extern void gimple_seq_set_location (gimple_seq, location_t);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org>
|
||||||
|
Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
PR c/16351
|
||||||
|
* gcc.dg/tree-ssa/isolate-2.c: Close comment.
|
||||||
|
* gcc.dg/tree-ssa/isolate-4.c: Likewise.
|
||||||
|
* gcc.dg/tree-ssa/wnull-dereference.c: New test.
|
||||||
|
* gcc.dg/tree-ssa/isolate-1.c: Test warnings with -Wnull-dereference.
|
||||||
|
* gcc.dg/tree-ssa/isolate-3.c: Likewise.
|
||||||
|
* gcc.dg/tree-ssa/isolate-5.c: Likewise.
|
||||||
|
|
||||||
2015-08-05 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
|
2015-08-05 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
|
||||||
|
|
||||||
PR middle-end/66311
|
PR middle-end/66311
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-O2 -fdump-tree-isolate-paths -fdelete-null-pointer-checks" } */
|
/* { dg-options "-O2 -fdump-tree-isolate-paths -fdelete-null-pointer-checks -Wnull-dereference" } */
|
||||||
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,8 +38,8 @@ d_type (struct d_info *di)
|
||||||
{
|
{
|
||||||
struct demangle_component *ret;
|
struct demangle_component *ret;
|
||||||
ret = d_make_empty (di);
|
ret = d_make_empty (di);
|
||||||
ret->type = 42;
|
ret->type = 42; /* { dg-warning "null pointer dereference" } */
|
||||||
ret->zzz = -1;
|
ret->zzz = -1; /* { dg-warning "null pointer dereference" } */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,8 +52,3 @@ d_type (struct d_info *di)
|
||||||
/* { dg-final { scan-tree-dump-times "->type = 42" 1 "isolate-paths"} } */
|
/* { dg-final { scan-tree-dump-times "->type = 42" 1 "isolate-paths"} } */
|
||||||
/* { dg-final { scan-tree-dump-times "->type ={v} 0" 1 "isolate-paths"} } */
|
/* { dg-final { scan-tree-dump-times "->type ={v} 0" 1 "isolate-paths"} } */
|
||||||
/* { dg-final { scan-tree-dump-times "->zzz" 1 "isolate-paths"} } */
|
/* { dg-final { scan-tree-dump-times "->zzz" 1 "isolate-paths"} } */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ bar (void)
|
||||||
from a PHI, the second with an explicit return 0 in the IL.
|
from a PHI, the second with an explicit return 0 in the IL.
|
||||||
|
|
||||||
We also verify that after isolation phi-cprop simplifies the
|
We also verify that after isolation phi-cprop simplifies the
|
||||||
return statement so that it returns &z directly.
|
return statement so that it returns &z directly. */
|
||||||
/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "isolate-paths"} } */
|
/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "isolate-paths"} } */
|
||||||
/* { dg-final { scan-tree-dump-times "return &z;" 1 "phicprop1"} } */
|
/* { dg-final { scan-tree-dump-times "return &z;" 1 "phicprop1"} } */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-O2 -fdump-tree-isolate-paths -fdelete-null-pointer-checks" } */
|
/* { dg-options "-O2 -fdump-tree-isolate-paths -fdelete-null-pointer-checks -Wnull-dereference" } */
|
||||||
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ static __inline__ void
|
||||||
VEC_rtx_gc_safe_grow (VEC_rtx_gc ** vec_, int size_, const char *file_,
|
VEC_rtx_gc_safe_grow (VEC_rtx_gc ** vec_, int size_, const char *file_,
|
||||||
unsigned line_, const char *function_)
|
unsigned line_, const char *function_)
|
||||||
{
|
{
|
||||||
((*vec_) ? &(*vec_)->base : 0)->num = size_;
|
((*vec_) ? &(*vec_)->base : 0)->num = size_; /* { dg-warning "null pointer dereference" } */
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void
|
static __inline__ void
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ bar (void)
|
||||||
a return statement.
|
a return statement.
|
||||||
|
|
||||||
We also verify that after isolation phi-cprop simplifies the
|
We also verify that after isolation phi-cprop simplifies the
|
||||||
return statement so that it returns &z directly.
|
return statement so that it returns &z directly. */
|
||||||
/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "isolate-paths"} } */
|
/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "isolate-paths"} } */
|
||||||
/* { dg-final { scan-tree-dump-times "foo .&z.;" 1 "phicprop1"} } */
|
/* { dg-final { scan-tree-dump-times "foo .&z.;" 1 "phicprop1"} } */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-O2 -fdelete-null-pointer-checks -fdump-tree-isolate-paths -fdump-tree-optimized" } */
|
/* { dg-options "-O2 -fdelete-null-pointer-checks -fdump-tree-isolate-paths -fdump-tree-optimized -Wnull-dereference" } */
|
||||||
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
||||||
|
|
||||||
struct demangle_component
|
struct demangle_component
|
||||||
|
|
@ -36,8 +36,8 @@ d_type (struct d_info *di)
|
||||||
{
|
{
|
||||||
struct demangle_component *ret;
|
struct demangle_component *ret;
|
||||||
ret = d_make_empty (di);
|
ret = d_make_empty (di);
|
||||||
foo (ret->type);
|
foo (ret->type); /* { dg-warning "null pointer dereference" } */
|
||||||
bar (ret->zzz);
|
bar (ret->zzz); /* { dg-warning "null pointer dereference" } */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* PR c/16531 */
|
||||||
|
/* { dg-options "-O2 -fdelete-null-pointer-checks -Wnull-dereference" } */
|
||||||
|
/* { dg-skip-if "" keeps_null_pointer_checks } */
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#define NULL (void *)0
|
||||||
|
#else
|
||||||
|
#define NULL nullptr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
int bar;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct t2
|
||||||
|
{
|
||||||
|
struct t *s;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test1 ()
|
||||||
|
{
|
||||||
|
struct t *s = NULL;
|
||||||
|
s->bar = 1; /* { dg-warning "null" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void test2 (struct t *s)
|
||||||
|
{
|
||||||
|
if (s == NULL && s->bar > 2) /* { dg-warning "null" } */
|
||||||
|
return;
|
||||||
|
|
||||||
|
s->bar = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test3 (struct t *s)
|
||||||
|
{
|
||||||
|
if (s != NULL || s->bar > 2) /* { dg-warning "null" } */
|
||||||
|
return;
|
||||||
|
|
||||||
|
s->bar = 3; /* { dg-warning "null" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
int test4 (struct t *s)
|
||||||
|
{
|
||||||
|
if (s != NULL && s->bar > 2) /* { dg-bogus "null" } */
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test5 (struct t *s)
|
||||||
|
{
|
||||||
|
if (s == NULL || s->bar > 2) /* { dg-bogus "null" } */
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test6 (struct t2 *s)
|
||||||
|
{
|
||||||
|
if (s->s == 0 && s->s->bar == 0) /* { dg-warning "null" } */
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test7 (struct t *s)
|
||||||
|
{
|
||||||
|
s = 0;
|
||||||
|
return s->bar; /* { dg-warning "null" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
int test8 ()
|
||||||
|
{
|
||||||
|
return ((struct t *)0)->bar; /* { dg-warning "null" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void test9 (struct t **s)
|
||||||
|
{
|
||||||
|
if (s == 0)
|
||||||
|
*s = 0; /* { dg-warning "null" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4938,7 +4938,7 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (infer_nonnull_range (stmt, op, true, true))
|
if (infer_nonnull_range (stmt, op))
|
||||||
{
|
{
|
||||||
*val_p = build_int_cst (TREE_TYPE (op), 0);
|
*val_p = build_int_cst (TREE_TYPE (op), 0);
|
||||||
*comp_code_p = NE_EXPR;
|
*comp_code_p = NE_EXPR;
|
||||||
|
|
|
||||||
|
|
@ -1615,7 +1615,7 @@ instrument_nonnull_arg (gimple_stmt_iterator *gsi)
|
||||||
{
|
{
|
||||||
tree arg = gimple_call_arg (stmt, i);
|
tree arg = gimple_call_arg (stmt, i);
|
||||||
if (POINTER_TYPE_P (TREE_TYPE (arg))
|
if (POINTER_TYPE_P (TREE_TYPE (arg))
|
||||||
&& infer_nonnull_range (stmt, arg, false, true))
|
&& infer_nonnull_range_by_attribute (stmt, arg))
|
||||||
{
|
{
|
||||||
gimple g;
|
gimple g;
|
||||||
if (!is_gimple_val (arg))
|
if (!is_gimple_val (arg))
|
||||||
|
|
@ -1680,7 +1680,7 @@ instrument_nonnull_return (gimple_stmt_iterator *gsi)
|
||||||
if (arg
|
if (arg
|
||||||
&& POINTER_TYPE_P (TREE_TYPE (arg))
|
&& POINTER_TYPE_P (TREE_TYPE (arg))
|
||||||
&& is_gimple_val (arg)
|
&& is_gimple_val (arg)
|
||||||
&& infer_nonnull_range (stmt, arg, false, true))
|
&& infer_nonnull_range_by_attribute (stmt, arg))
|
||||||
{
|
{
|
||||||
basic_block then_bb, fallthru_bb;
|
basic_block then_bb, fallthru_bb;
|
||||||
*gsi = create_cond_insert_point (gsi, true, false, true,
|
*gsi = create_cond_insert_point (gsi, true, false, true,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue