From patchwork Wed Jul 22 15:29:52 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: 498600 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 965F21402C8 for ; Thu, 23 Jul 2015 01:30:45 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=jW+C3cyI; 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=pfnh2iecEVEcLN+7iqgOJjV2ZasilWDFxvR3amvABicLSJ KKIZa5cpA7W+wYpj3ImnsYvjH++gODfgUie/3jfI09XYt9ZvJFX4Vps+72OyOfUT 9ePLoFizqeBXSDh3SVSkvBxC7bldu25IBK9OyE5tqVLQdwZb0vthzjWe/Ns28= 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=39HQ7CTss+5+tSWL8UPeyGoEZz4=; b=jW+C3cyI91E+cLvTd3ee KvOf1uX84PFsaZYpopz7Y1qEwKjUPU6ctUjByfLCJCB5uLTYoy7R4sXsQQZGqILh TqpSsErxyAOsQzmAbrTKIolYF/DigPSquEeLivw6F3D1eDdKZMcWR59Iyz09GL0A f/egI5XiVQogu7BimVohwLg= Received: (qmail 46047 invoked by alias); 22 Jul 2015 15:30:38 -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 46037 invoked by uid 89); 22 Jul 2015 15:30:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-wi0-f176.google.com Received: from mail-wi0-f176.google.com (HELO mail-wi0-f176.google.com) (209.85.212.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 22 Jul 2015 15:30:35 +0000 Received: by wibud3 with SMTP id ud3so178247652wib.0 for ; Wed, 22 Jul 2015 08:30:32 -0700 (PDT) X-Received: by 10.194.133.73 with SMTP id pa9mr6218757wjb.148.1437579032117; Wed, 22 Jul 2015 08:30:32 -0700 (PDT) MIME-Version: 1.0 Received: by 10.28.188.139 with HTTP; Wed, 22 Jul 2015 08:29:52 -0700 (PDT) From: =?UTF-8?B?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= Date: Wed, 22 Jul 2015 17:29:52 +0200 Message-ID: Subject: PR c/16351 Extend Wnonnull for returns_nonnull To: Gcc Patch List , Jason Merrill , "Joseph S. Myers" , Jeff Law While looking at PR c/16351, I noticed that all tests proposed for -Wnull-attribute (https://gcc.gnu.org/ml/gcc-patches/2014-01/msg01715.html) could be warned from the FEs by simply extending the existing Wnonnull. Bootstrapped and regression tested on x86_64-linux-gnu. OK? gcc/ChangeLog: 2015-07-22 Manuel López-Ibáñez PR c/16351 * doc/invoke.texi (Wnonnull): Document behavior for returns_nonnull. gcc/testsuite/ChangeLog: 2015-07-22 Manuel López-Ibáñez PR c/16351 * c-c++-common/wnonnull-1.c: New test. gcc/cp/ChangeLog: 2015-07-22 Manuel López-Ibáñez PR c/16351 * typeck.c (check_return_expr): Call maybe_warn_returns_nonnull. gcc/c-family/ChangeLog: 2015-07-22 Manuel López-Ibáñez PR c/16351 * c-common.c (maybe_warn_returns_nonnull): New. * c-common.h (maybe_warn_returns_nonnull): Declare. gcc/c/ChangeLog: 2015-07-22 Manuel López-Ibáñez PR c/16351 * c-typeck.c (c_finish_return): Call maybe_warn_returns_nonnull. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 225868) +++ gcc/doc/invoke.texi (working copy) @@ -3709,11 +3709,13 @@ formats that may yield only a two-digit @item -Wnonnull @opindex Wnonnull @opindex Wno-nonnull Warn about passing a null pointer for arguments marked as -requiring a non-null value by the @code{nonnull} function attribute. +requiring a non-null value by the @code{nonnull} function attribute +or returning a null pointer from a function declared with the attribute +@code{returns_nonnull}. @option{-Wnonnull} is included in @option{-Wall} and @option{-Wformat}. It can be disabled with the @option{-Wno-nonnull} option. @item -Winit-self @r{(C, C++, Objective-C and Objective-C++ only)} Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 225868) +++ gcc/c-family/c-common.c (working copy) @@ -9508,10 +9508,22 @@ check_nonnull_arg (void * ARG_UNUSED (ct if (integer_zerop (param)) warning (OPT_Wnonnull, "null argument where non-null required " "(argument %lu)", (unsigned long) param_num); } +/* Possibly warn if RETVAL is a null pointer and FNDECL is declared + with attribute returns_nonnull. LOC is the location of RETVAL. */ + +void +maybe_warn_returns_nonnull (location_t loc, tree fndecl, tree retval) +{ + if (integer_zerop (retval) + && lookup_attribute ("returns_nonnull", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + warning_at (loc, OPT_Wnonnull, "null return value where non-null required"); +} + /* Helper for nonnull attribute handling; fetch the operand number from the attribute argument list. */ static bool get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 225868) +++ gcc/c-family/c-common.h (working copy) @@ -1049,10 +1049,11 @@ extern void do_warn_double_promotion (tr extern void set_underlying_type (tree); extern void record_types_used_by_current_var_decl (tree); extern void record_locally_defined_typedef (tree); extern void maybe_record_typedef_use (tree); extern void maybe_warn_unused_local_typedefs (void); +extern void maybe_warn_returns_nonnull (location_t, tree, tree); extern void maybe_warn_bool_compare (location_t, enum tree_code, tree, tree); extern vec *make_tree_vector (void); extern void release_tree_vector (vec *); extern vec *make_tree_vector_single (tree); extern vec *make_tree_vector_from_list (tree); Index: gcc/c/c-typeck.c =================================================================== --- gcc/c/c-typeck.c (revision 225868) +++ gcc/c/c-typeck.c (working copy) @@ -9372,10 +9372,11 @@ c_finish_return (location_t loc, tree re { semantic_type = TREE_TYPE (retval); retval = TREE_OPERAND (retval, 0); } retval = c_fully_fold (retval, false, NULL); + maybe_warn_returns_nonnull (loc, current_function_decl, retval); if (semantic_type) retval = build1 (EXCESS_PRECISION_EXPR, semantic_type, retval); } if (!retval) 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/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 225868) +++ gcc/cp/typeck.c (working copy) @@ -8702,10 +8702,12 @@ check_return_expr (tree retval, bool *no /* We don't need to do any conversions when there's nothing being returned. */ if (!retval) return NULL_TREE; + maybe_warn_returns_nonnull (input_location, current_function_decl, retval); + /* Do any required conversions. */ if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl)) /* No conversions are required. */ ; else