From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 58021 invoked by alias); 24 Jul 2017 19:39:51 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 57777 invoked by uid 89); 24 Jul 2017 19:39:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 24 Jul 2017 19:39:48 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2606DC074540 for ; Mon, 24 Jul 2017 19:31:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2606DC074540 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=dmalcolm@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 2606DC074540 Received: from c64.redhat.com (ovpn-112-25.phx2.redhat.com [10.3.112.25]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4ECBE69720; Mon, 24 Jul 2017 19:31:02 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 08/17] C: highlight return types when complaining about mismatches Date: Mon, 24 Jul 2017 19:39:00 -0000 Message-Id: <1500926714-56988-9-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1500926714-56988-1-git-send-email-dmalcolm@redhat.com> References: <1500926714-56988-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes X-SW-Source: 2017-07/txt/msg01463.txt.bz2 This patch to the C frontend uses the BLT infrastructure to highlight the return type of a function when complaining about code within the function that doesn't match it. For example, given: warning: 'return' with a value, in function returning void return 42; ^~ note: declared here void test_1 (void) ^~~~~~ the patch converts the location and wording of the note to highlight the return type: warning: 'return' with a value, in function returning void return 42; ^~ note: the return type was declared as 'void' here void test_1 (void) ^~~~ gcc/c/ChangeLog: * c-typeck.c (get_location_of_return_type): New function. (attempt_to_highlight_return_type): New function. (c_finish_return): Convert "inform" calls to calls to attempt_to_highlight_return_type. gcc/testsuite/ChangeLog: * gcc.dg/bad-return-type.c: New test case. --- gcc/c/c-typeck.c | 57 +++++++++++++++++++++++++++-- gcc/testsuite/gcc.dg/bad-return-type.c | 67 ++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/bad-return-type.c diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index c37cc33..7362246 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -9884,6 +9884,57 @@ c_finish_goto_ptr (location_t loc, tree expr) return add_stmt (t); } +/* Attempt to use BLT locate the return type within FNDECL, returning + UNKNOWN_LOCATION if there is a problem (or if BLT is disabled). */ + +static location_t +get_location_of_return_type (tree fndecl) +{ + blt_node *node = blt_get_node_for_tree (fndecl); + if (!node) + return UNKNOWN_LOCATION; + + /* We have a direct-declarator. + Go up two to find the external-declaration. */ + blt_node *ext_decl = node->get_ancestor_of_kind (BLT_EXTERNAL_DECLARATION); + if (!ext_decl) + return UNKNOWN_LOCATION; + + /* Locate the declaration-specifiers within the direct-declarator. */ + blt_node *dss + = ext_decl->get_first_child_of_kind (BLT_DECLARATION_SPECIFIERS); + if (!dss) + return UNKNOWN_LOCATION; + + /* Locate the type-specifier within the decl specifiers. */ + blt_node *ts = dss->get_first_child_of_kind (BLT_TYPE_SPECIFIER); + if (!ts) + return UNKNOWN_LOCATION; + + /* FIXME: we want just the return type, not "extern" etc. */ + return ts->get_range (); +} + +/* Attempt to locate the return type within FNDECL; if successful, + emit a note highlighting the return type; otherwise emit a note + highlighting the decl. */ + +static void +attempt_to_highlight_return_type (tree fndecl) +{ + location_t ret_type_loc = get_location_of_return_type (fndecl); + if (ret_type_loc == UNKNOWN_LOCATION) + inform (DECL_SOURCE_LOCATION (fndecl), "declared here"); + else + { + tree result = DECL_RESULT (fndecl); + tree return_type = TREE_TYPE (result); + inform (ret_type_loc, "the return type was declared as %qT here", + return_type); + } +} + + /* Generate a C `return' statement. RETVAL is the expression for what to return, or a null pointer for `return;' with no value. LOC is the location of the return statement, or the location of the expression, @@ -9956,8 +10007,7 @@ c_finish_return (location_t loc, tree retval, tree origtype) "% with no value, in function returning non-void"); no_warning = true; if (warned_here) - inform (DECL_SOURCE_LOCATION (current_function_decl), - "declared here"); + attempt_to_highlight_return_type (current_function_decl); } } else if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE) @@ -9973,8 +10023,7 @@ c_finish_return (location_t loc, tree retval, tree origtype) (xloc, OPT_Wpedantic, "ISO C forbids " "% with expression, in function returning void"); if (warned_here) - inform (DECL_SOURCE_LOCATION (current_function_decl), - "declared here"); + attempt_to_highlight_return_type (current_function_decl); } else { diff --git a/gcc/testsuite/gcc.dg/bad-return-type.c b/gcc/testsuite/gcc.dg/bad-return-type.c new file mode 100644 index 0000000..095b767 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bad-return-type.c @@ -0,0 +1,67 @@ +/* Verify that we can highlight the return type for various kinds + of bogus return. */ + +/* { dg-options "-fdiagnostics-show-caret -fblt -Wreturn-type" } */ + +void test_1 (void) // { dg-line return_line } +{ + return 42; // { dg-warning "'return' with a value, in function returning void" } + /* { dg-begin-multiline-output "" } + return 42; + ^~ + { dg-end-multiline-output "" } */ + /* { dg-message "the return type was declared as 'void' here" "" { target *-*-* } return_line } */ + /* { dg-begin-multiline-output "" } + void test_1 (void) + ^~~~ + { dg-end-multiline-output "" } */ +} + +/* As before, but with different whitespace. */ + +void // { dg-line return_line_2 } +test_2 (void) +{ + return 42; // { dg-warning "'return' with a value, in function returning void" } + /* { dg-begin-multiline-output "" } + return 42; + ^~ + { dg-end-multiline-output "" } */ + /* { dg-message "the return type was declared as 'void' here" "" { target *-*-* } return_line_2 } */ + /* { dg-begin-multiline-output "" } + void + ^~~~ + { dg-end-multiline-output "" } */ +} + +/* As before, but with "extern". */ + +extern void test_3 (void) // { dg-line return_line_3 } +{ + return 42; // { dg-warning "'return' with a value, in function returning void" } + /* { dg-begin-multiline-output "" } + return 42; + ^~ + { dg-end-multiline-output "" } */ + /* { dg-message "the return type was declared as 'void' here" "" { target *-*-* } return_line_3 } */ + /* { dg-begin-multiline-output "" } + extern void test_3 (void) + ^~~~ + { dg-end-multiline-output "" } */ +} + +/* Type mismatch for non-void return. */ + +extern int test_4 (void) // { dg-line return_line_4 } +{ + return; // { dg-warning "'return' with no value, in function returning non-void" } + /* { dg-begin-multiline-output "" } + return; + ^~~~~~ + { dg-end-multiline-output "" } */ + /* { dg-message "the return type was declared as 'int' here" "" { target *-*-* } return_line_4 } */ + /* { dg-begin-multiline-output "" } + extern int test_4 (void) + ^~~ + { dg-end-multiline-output "" } */ +} -- 1.8.5.3