From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 42184 invoked by alias); 12 Nov 2015 19:46:59 -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 42172 invoked by uid 89); 12 Nov 2015 19:46:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 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 (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 12 Nov 2015 19:46:57 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 2896D461DA; Thu, 12 Nov 2015 19:46:56 +0000 (UTC) Received: from [10.3.232.152] (vpn-232-152.phx2.redhat.com [10.3.232.152]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tACJktoo008517; Thu, 12 Nov 2015 14:46:55 -0500 Message-ID: <1447357615.7830.30.camel@surprise> Subject: Re: [PATCH 02/02] C FE: add fix-it hint for . vs -> From: David Malcolm To: Joseph Myers Cc: gcc-patches@gcc.gnu.org Date: Thu, 12 Nov 2015 19:46:00 -0000 In-Reply-To: References: <1447173325-48683-1-git-send-email-dmalcolm@redhat.com> <1447173325-48683-2-git-send-email-dmalcolm@redhat.com> Content-Type: multipart/mixed; boundary="=-qGkRxo8AIOaQS+czqwRX" Mime-Version: 1.0 X-IsSubscribed: yes X-SW-Source: 2015-11/txt/msg01584.txt.bz2 --=-qGkRxo8AIOaQS+czqwRX Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Content-length: 964 On Tue, 2015-11-10 at 17:55 +0000, Joseph Myers wrote: > On Tue, 10 Nov 2015, David Malcolm wrote: > > > This is the most trivial example of a real fix-it example I could think > > of: if the user writes > > ptr.field > > rather than ptr->field. > > > > gcc/c/ChangeLog: > > * c-typeck.c (build_component_ref): Special-case POINTER_TYPE when > > generating a "not a structure of union" error message, and > > suggest a "->" rather than a ".", providing a fix-it hint. > > I wonder if this should be restricted to the case where the pointer's > target is of structure or union type. Probably. Attached is an updated version of the patch that does so. > At least, if it's some other type, > more of a fix is needed than just using -> (e.g. converting from void * to > a pointer to the relevant type). If so, then the attached patch simply does the status quo (I don't think we want to try too hard for this case). I've added a test case for this. --=-qGkRxo8AIOaQS+czqwRX Content-Disposition: attachment; filename="0001-C-FE-add-fix-it-hint-for-.-vs.patch" Content-Type: text/x-patch; name="0001-C-FE-add-fix-it-hint-for-.-vs.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit Content-length: 4121 >From 12aa183d693db59cbc5d8a268749d577e729425c Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 8 Sep 2015 12:56:00 -0400 Subject: [PATCH] C FE: add fix-it hint for . vs -> This is the most trivial example of a real fix-it example I could think of: if the user writes ptr.field rather than ptr->field. gcc/c/ChangeLog: * c-typeck.c (should_suggest_deref_p): New function. (build_component_ref): Special-case POINTER_TYPE when generating a "not a structure of union" error message, and suggest a "->" rather than a ".", providing a fix-it hint. gcc/testsuite/ChangeLog: * gcc.dg/fixits.c: New file. --- gcc/c/c-typeck.c | 39 +++++++++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/fixits.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/fixits.c diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index c2e16c6..bdb2d12 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2249,6 +2249,33 @@ lookup_field (tree type, tree component) return tree_cons (NULL_TREE, field, NULL_TREE); } +/* Support function for build_component_ref's error-handling. + + Given DATUM_TYPE, and "DATUM.COMPONENT", where DATUM is *not* a + struct or union, should we suggest "DATUM->COMPONENT" as a hint? */ + +static bool +should_suggest_deref_p (tree datum_type) +{ + /* We don't do it for Objective-C, since Objective-C 2.0 dot-syntax + allows "." for ptrs; we could be handling a failed attempt + to access a property. */ + if (c_dialect_objc ()) + return false; + + /* Only suggest it for pointers... */ + if (TREE_CODE (datum_type) != POINTER_TYPE) + return false; + + /* ...to structs/unions. */ + tree underlying_type = TREE_TYPE (datum_type); + enum tree_code code = TREE_CODE (underlying_type); + if (code == RECORD_TYPE || code == UNION_TYPE) + return true; + else + return false; +} + /* Make an expression to refer to the COMPONENT field of structure or union value DATUM. COMPONENT is an IDENTIFIER_NODE. LOC is the location of the COMPONENT_REF. */ @@ -2336,6 +2363,18 @@ build_component_ref (location_t loc, tree datum, tree component) return ref; } + else if (should_suggest_deref_p (type)) + { + /* Special-case the error message for "ptr.field" for the case + where the user has confused "." vs "->". */ + rich_location richloc (line_table, loc); + /* "loc" should be the "." token. */ + richloc.add_fixit_replace (source_range::from_location (loc), "->"); + error_at_rich_loc (&richloc, + "%qE is a pointer; did you mean to use %<->%>?", + datum); + return error_mark_node; + } else if (code != ERROR_MARK) error_at (loc, "request for member %qE in something not a structure or union", diff --git a/gcc/testsuite/gcc.dg/fixits.c b/gcc/testsuite/gcc.dg/fixits.c new file mode 100644 index 0000000..06c9995 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fixits.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-show-caret" } */ + +struct foo { int x; }; +union u { int x; }; + +/* Verify that we issue a hint for "." used with a ptr to a struct. */ + +int test_1 (struct foo *ptr) +{ + return ptr.x; /* { dg-error "'ptr' is a pointer; did you mean to use '->'?" } */ +/* { dg-begin-multiline-output "" } + return ptr.x; + ^ + -> + { dg-end-multiline-output "" } */ +} + +/* Likewise for a ptr to a union. */ + +int test_2 (union u *ptr) +{ + return ptr.x; /* { dg-error "'ptr' is a pointer; did you mean to use '->'?" } */ +/* { dg-begin-multiline-output "" } + return ptr.x; + ^ + -> + { dg-end-multiline-output "" } */ +} + +/* Verify that we don't issue a hint for a ptr to something that isn't a + struct or union. */ + +int test_3 (void **ptr) +{ + return ptr.x; /* { dg-error "request for member 'x' in something not a structure or union" } */ +/* { dg-begin-multiline-output "" } + return ptr.x; + ^ + { dg-end-multiline-output "" } */ +} -- 1.8.5.3 --=-qGkRxo8AIOaQS+czqwRX--