From patchwork Wed Jul 22 15:52:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= X-Patchwork-Id: 498658 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E8EEB1402AE for ; Thu, 23 Jul 2015 01:53:37 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=BHngF4ir; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=xVgjMto5cDojxJA+29zI9XrEGAZQ/HG5HqjzayjaspBzjc No+4OJwleW6dEXBD0j2k2d8M86Ho1AavxQGs8yjgTDhsSR0bz8hdT28HKwcHlqmo 1+KkwOZOINtSg4p+354ysWvUeq+OtC8vJZXbwn5bHy8p9bk88GWfjF7q4KFN0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=4JQAQTYYPsUy/P+uMc57iB38EC8=; b=BHngF4irN60klOWpdHpC OtDUQIApfU1cx9n/cnicn1T5bXDPPE2tjyPUk6+mi9pYE8PdSz3Dj4cnwumHch+f BF3FLqV6Sd5txM18pmP4CmzgWeDvFzFEXpAQYPEfH+5Whta9FDX+8wPe1TA8dplS o+FsCab/lH/uSOm4kAS36Nc= Received: (qmail 33231 invoked by alias); 22 Jul 2015 15:53:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 33220 invoked by uid 89); 22 Jul 2015 15:53:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.0 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-wi0-f173.google.com Received: from mail-wi0-f173.google.com (HELO mail-wi0-f173.google.com) (209.85.212.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 22 Jul 2015 15:53:26 +0000 Received: by wibud3 with SMTP id ud3so160256174wib.1 for ; Wed, 22 Jul 2015 08:53:22 -0700 (PDT) X-Received: by 10.194.201.71 with SMTP id jy7mr6625876wjc.93.1437580402371; Wed, 22 Jul 2015 08:53:22 -0700 (PDT) MIME-Version: 1.0 Received: by 10.28.188.139 with HTTP; Wed, 22 Jul 2015 08:52:42 -0700 (PDT) From: =?UTF-8?B?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= Date: Wed, 22 Jul 2015 17:52:42 +0200 Message-ID: Subject: PR middle-end/16351 NULL dereference warnings To: Gcc Patch List , Richard Biener , Jakub Jelinek , Jeff Law , Florian Weimer I took the patch in https://gcc.gnu.org/ml/gcc-patches/2014-01/msg01715.html and removed the Wnull-attribute part, since most of it can be done from the FE as shown in https://gcc.gnu.org/ml/gcc-patches/2015-07/msg01857.html and also to make the patch smaller and easier to review. I also fixed the comments by Florian here: https://gcc.gnu.org/ml/gcc-patches/2014-02/msg00149.html and added more tests from the PR and its duplicates (one xfailed, I'll open a new PR about it). Futher cleanups may be possible (infer_nonnull_range_by_attribute checks flag_delete_null_pointer_checks, which seems weird to me but it matches the existing behavior of infer_nonnull_range). I added this to Wall to get as much testing as possible, we can always move it to Wextra or disable it by default just before the release if it turns out to be too noisy. Boostrapped and regression tested on x86_64-linux-gnu. OK? gcc/ChangeLog: 2015-07-22 Manuel López-Ibáñez Jeff Law 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-07-22 Manuel López-Ibáñez Jeff Law 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. * c-c++-common/wnonnull-1.c: New test. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 225868) +++ gcc/tree-vrp.c (working copy) @@ -4936,11 +4936,11 @@ infer_value_range (gimple stmt, tree op, break; if (e == NULL) 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); *comp_code_p = NE_EXPR; return true; } Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 225868) +++ gcc/doc/invoke.texi (working copy) @@ -258,10 +258,11 @@ Objective-C and Objective-C++ Dialects}. -Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol -Wignored-qualifiers -Wincompatible-pointer-types @gol -Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol -Winit-self -Winline -Wno-int-conversion @gol -Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol +-Wnull-dereference @gol -Winvalid-pch -Wlarger-than=@var{len} -Wunsafe-loop-optimizations @gol -Wlogical-op -Wlogical-not-parentheses -Wlong-long @gol -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args @gol -Wmisleading-indentation -Wmissing-braces @gol -Wmissing-field-initializers -Wmissing-include-dirs @gol @@ -4130,10 +4133,20 @@ All the above @option{-Wunused} options In order to get a warning about an unused function parameter, you must either specify @option{-Wextra -Wunused} (note that @option{-Wall} implies @option{-Wunused}), or separately specify @option{-Wunused-parameter}. +@item -Wnull-dereference +@opindex Wnull-dereference +@opindex Wno-null-dereference +Warn if the compiler detects paths which trigger erroneous or +undefined behaviour 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 @opindex Wuninitialized @opindex Wno-uninitialized Warn if an automatic variable is used without first being initialized or if a variable may be clobbered by a @code{setjmp} call. In C++, Index: gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c (revision 225868) +++ gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c (working copy) @@ -33,10 +33,10 @@ bar (void) returns non-null attribute to isolate a path where NULL flows into a return statement. We test this twice, once where the NULL flows from a PHI, the second with an explicit return 0 in the IL. 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 "return &z;" 1 "phicprop1"} } */ Index: gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c (revision 225868) +++ gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c (working copy) @@ -22,10 +22,10 @@ bar (void) /* We testing that the path isolation code can take advantage of the returns non-null attribute to isolate a path where NULL flows into a return statement. 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 "foo .&z.;" 1 "phicprop1"} } */ Index: gcc/testsuite/gcc.dg/tree-ssa/wnull-dereference.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/wnull-dereference.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/wnull-dereference.c (revision 0) @@ -0,0 +1,80 @@ +/* { 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" } */ +} + +void test4 (struct t *s) +{ + if (s != NULL && s->bar > 2) /* { dg-bogus "null" } */ + return; +} + +void test5 (struct t *s) +{ + if (s == NULL || s->bar > 2) /* { dg-bogus "null" } */ + return; + +} + +void test6 (struct t2 *s) +{ + if (s->s == 0 && s->s->bar == 0) /* { dg-warning "null" "null" { xfail *-*-* } } */ + return; +} + +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" } */ +} + + Index: gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c (revision 225868) +++ gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c (working copy) @@ -1,8 +1,7 @@ - /* { 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 } */ struct demangle_component { @@ -37,12 +36,12 @@ d_make_empty (struct d_info *di) struct demangle_component * d_type (struct d_info *di) { struct demangle_component *ret; ret = d_make_empty (di); - ret->type = 42; - ret->zzz = -1; + ret->type = 42; /* { dg-warning "null pointer dereference" } */ + ret->zzz = -1; /* { dg-warning "null pointer dereference" } */ return ret; } /* We're testing three aspects of isolation here. First that isolation occurs, second that if we have two null dereferences in a block that @@ -51,10 +50,5 @@ d_type (struct d_info *di) and finally that we set the RHS of the store to zero. */ /* { dg-final { scan-tree-dump-times "__builtin_trap" 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 "->zzz" 1 "isolate-paths"} } */ - - - - - Index: gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c (revision 225868) +++ gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c (working copy) @@ -1,7 +1,7 @@ /* { 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 } */ typedef __SIZE_TYPE__ size_t; extern void *memset (void *__s, int __c, size_t __n) @@ -27,11 +27,11 @@ typedef struct VEC_rtx_gc static __inline__ void VEC_rtx_gc_safe_grow (VEC_rtx_gc ** vec_, int size_, const char *file_, 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 VEC_rtx_gc_safe_grow_cleared (VEC_rtx_gc ** vec_, int size_, const char *file_, unsigned line_, Index: gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c (revision 225868) +++ gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c (working copy) @@ -1,7 +1,7 @@ /* { 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 } */ struct demangle_component { @@ -34,12 +34,12 @@ d_make_empty (struct d_info *di) struct demangle_component * d_type (struct d_info *di) { struct demangle_component *ret; ret = d_make_empty (di); - foo (ret->type); - bar (ret->zzz); + foo (ret->type); /* { dg-warning "null pointer dereference" } */ + bar (ret->zzz); /* { dg-warning "null pointer dereference" } */ return ret; } /* We're testing two aspects of isolation here. First that isolation occurs, second that if we have two null dereferences in a block that Index: gcc/testsuite/c-c++-common/wnonnull-1.c =================================================================== --- gcc/testsuite/c-c++-common/wnonnull-1.c (revision 0) +++ gcc/testsuite/c-c++-common/wnonnull-1.c (revision 0) @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-Wnonnull" } */ + + +extern void foo(void *) __attribute__ ((__nonnull__ (1))); + +int z; +int y; + +void +com (int a) +{ + foo (a == 42 ? &z : (void *) 0); /* { dg-warning "null" } */ +} + +void +bar (void) +{ + foo ((void *)0); /* { dg-warning "null" } */ +} + +int * foo_r(int a) __attribute__((returns_nonnull)); +int * bar_r(void) __attribute__((returns_nonnull)); + +int * +foo_r(int a) +{ + switch (a) + { + case 0: + return &z; + default: + return (int *)0; /* { dg-warning "null" } */ + } +} + +int * +bar_r (void) +{ + return 0; /* { dg-warning "null" } */ +} + Index: gcc/gimple-ssa-isolate-paths.c =================================================================== --- gcc/gimple-ssa-isolate-paths.c (revision 225868) +++ gcc/gimple-ssa-isolate-paths.c (working copy) @@ -329,15 +329,33 @@ find_implicit_erroneous_behaviour (void) in other blocks would require more complex path isolation code. */ if (gimple_bb (use_stmt) != bb) continue; - if (infer_nonnull_range (use_stmt, lhs, - flag_isolate_erroneous_paths_dereference, - flag_isolate_erroneous_paths_attribute)) + bool by_dereference + = infer_nonnull_range_by_dereference (use_stmt, lhs); + 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, use_stmt, lhs, false); /* When we remove an incoming edge, we need to reprocess the Ith element. */ @@ -379,17 +397,33 @@ find_explicit_erroneous_behaviour (void) because of jump threading and constant propagation. */ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) { gimple stmt = gsi_stmt (si); - /* By passing null_pointer_node, we can use infer_nonnull_range - to detect explicit NULL pointer dereferences and other uses - where a non-NULL value is required. */ - if (infer_nonnull_range (stmt, null_pointer_node, - flag_isolate_erroneous_paths_dereference, - flag_isolate_erroneous_paths_attribute)) + /* By passing null_pointer_node, we can use the + infer_nonnull_range functions to detect explicit NULL + pointer dereferences and other uses where a non-NULL + value is required. */ + + 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, null_pointer_node); /* And finally, remove all outgoing edges from BB. */ edge e; @@ -532,11 +566,12 @@ public: virtual bool gate (function *) { /* If we do not have a suitable builtin function for the trap statement, then do not perform the optimization. */ 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 *) { return gimple_ssa_isolate_erroneous_paths (); Index: gcc/ubsan.c =================================================================== --- gcc/ubsan.c (revision 225868) +++ gcc/ubsan.c (working copy) @@ -1613,11 +1613,11 @@ instrument_nonnull_arg (gimple_stmt_iter loc[1] = UNKNOWN_LOCATION; for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++) { tree arg = gimple_call_arg (stmt, i); if (POINTER_TYPE_P (TREE_TYPE (arg)) - && infer_nonnull_range (stmt, arg, false, true)) + && infer_nonnull_range_by_attribute (stmt, arg)) { gimple g; if (!is_gimple_val (arg)) { g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg); @@ -1678,11 +1678,11 @@ instrument_nonnull_return (gimple_stmt_i loc[0] = gimple_location (stmt); loc[1] = UNKNOWN_LOCATION; if (arg && POINTER_TYPE_P (TREE_TYPE (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; *gsi = create_cond_insert_point (gsi, true, false, true, &then_bb, &fallthru_bb); gimple g = gimple_build_cond (EQ_EXPR, arg, Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 225868) +++ gcc/common.opt (working copy) @@ -590,10 +590,15 @@ Common RejectNegative Joined Warning Und Wlarger-than= Common RejectNegative Joined UInteger Warning -Wlarger-than= Warn if an object is larger than bytes +Wnull-dereference +Common Var(warn_null_dereference) Warning EnabledBy(Wall) +Warn if the compiler detects paths which trigger erroneous or undefined +behaviour due to dereferencing a NULL pointer. + Wunsafe-loop-optimizations Common Var(warn_unsafe_loop_optimizations) Warning Warn if the loop cannot be optimized due to nontrivial assumptions. Wmissing-noreturn Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 225868) +++ gcc/gimple.c (working copy) @@ -2616,35 +2616,52 @@ check_loadstore (gimple, tree op, tree, && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0)) return true; 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 +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 (gimple stmt, tree op, bool dereference, bool attribute) +infer_nonnull_range_by_dereference (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 (dereference - && walk_stmt_load_store_ops (stmt, (void *)op, - check_loadstore, check_loadstore)) + if (walk_stmt_load_store_ops (stmt, (void *)op, + check_loadstore, check_loadstore)) return true; - if (attribute - && is_gimple_call (stmt) && !gimple_call_internal_p (stmt)) + return false; +} + +/* 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 attrs = TYPE_ATTRIBUTES (fntype); for (; attrs; attrs = TREE_CHAIN (attrs)) { @@ -2679,17 +2696,16 @@ infer_nonnull_range (gimple stmt, tree o } } /* 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. */ - if (attribute) - if (greturn *return_stmt = dyn_cast (stmt)) - if (gimple_return_retval (return_stmt) - && operand_equal_p (gimple_return_retval (return_stmt), op, 0) - && lookup_attribute ("returns_nonnull", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - return true; + if (greturn *return_stmt = dyn_cast (stmt)) + if (gimple_return_retval (return_stmt) + && operand_equal_p (gimple_return_retval (return_stmt), op, 0) + && lookup_attribute ("returns_nonnull", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + return true; return false; } /* Compare two case labels. Because the front end should already have Index: gcc/gimple.h =================================================================== --- gcc/gimple.h (revision 225868) +++ gcc/gimple.h (working copy) @@ -1399,11 +1399,13 @@ extern bool gimple_call_builtin_p (const extern bool gimple_call_builtin_p (const_gimple, enum built_in_class); extern bool gimple_call_builtin_p (const_gimple, enum built_in_function); extern bool gimple_asm_clobbers_memory_p (const gasm *); extern void dump_decl_set (FILE *, bitmap); 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); extern void preprocess_case_label_vec_for_gimple (vec, tree, tree *); extern void gimple_seq_set_location (gimple_seq, location_t); extern void gimple_seq_discard (gimple_seq); extern void maybe_remove_unused_call_args (struct function *, gimple);