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

2015-11-12 Thread Joseph Myers
On Thu, 12 Nov 2015, David Malcolm wrote:

> On Tue, 2015-11-10 at 17:55 +, 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.

This patch is OK.

-- 
Joseph S. Myers
jos...@codesourcery.com


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

2015-11-12 Thread David Malcolm
On Tue, 2015-11-10 at 17:55 +, 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 
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 000..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 

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

2015-11-10 Thread Joseph Myers
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.  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).

-- 
Joseph S. Myers
jos...@codesourcery.com


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

2015-11-10 Thread David Malcolm
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.

gcc/testsuite/ChangeLog:
* gcc.dg/fixits.c: New file.
---
 gcc/c/c-typeck.c  | 15 +++
 gcc/testsuite/gcc.dg/fixits.c | 14 ++
 2 files changed, 29 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..6fe1ca8 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2336,6 +2336,21 @@ build_component_ref (location_t loc, tree datum, tree 
component)
 
   return ref;
 }
+  else if (code == POINTER_TYPE && !c_dialect_objc ())
+{
+  /* Special-case the error message for "ptr.field" for the case
+where the user has confused "." vs "->".
+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.  */
+  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 000..3b8c8a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fixits.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+struct foo { int x; };
+
+int test (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 "" } */
+}
-- 
1.8.5.3