This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 02/02] C FE: add fix-it hint for . vs ->


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.

>From 12aa183d693db59cbc5d8a268749d577e729425c Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]