[PATCH] C++: fix-it hint for missing parentheses

David Malcolm dmalcolm@redhat.com
Mon Nov 12 02:28:00 GMT 2018


Consider:

  class t1
  {
  public:
    double length () const { return m_length; }
  private:
    double m_length;
  };

missing-parens-fixit.C: In function 'bool test_1(const t1&)':
missing-parens-fixit.C:14:15: error: invalid use of member function
  'double t1::length() const' (did you forget the '()' ?)
   14 |   return inst.length > 0.0;
      |          ~~~~~^~~~~~

This patch adds a fix-it hint for the case where the member function
takes no parameters, suggesting the addition of the parentheses:

   14 |   return inst.length > 0.0;
      |          ~~~~~^~~~~~
      |                     ()

so that an IDE can potentially apply the fix.

OK for trunk?

gcc/cp/ChangeLog:
	* typeck2.c: Include "gcc-rich-location.h".
	(cxx_incomplete_type_diagnostic): When complaining about possibly
	missing parens, add a fix-it hint if the member function takes no
	additional params.

gcc/ChangeLog:
	* diagnostic-core.h (emit_diagnostic): New decl.
	* diagnostic.c (emit_diagnostic): New overload, taking a
	rich_location *.

gcc/testsuite/ChangeLog:
	* g++.dg/parse/missing-parens-fixit.C: New test.
---
 gcc/cp/typeck2.c                                  | 14 +++++++---
 gcc/diagnostic-core.h                             |  2 ++
 gcc/diagnostic.c                                  | 14 ++++++++++
 gcc/testsuite/g++.dg/parse/missing-parens-fixit.C | 32 +++++++++++++++++++++++
 4 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/missing-parens-fixit.C

diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index fec1db0..c3c59a8 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "varasm.h"
 #include "intl.h"
+#include "gcc-rich-location.h"
 
 static tree
 process_init_constructor (tree type, tree init, int nested,
@@ -507,9 +508,16 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
 
 	if (DECL_FUNCTION_MEMBER_P (member)
 	    && ! flag_ms_extensions)
-	  emit_diagnostic (diag_kind, loc, 0,
-			   "invalid use of member function %qD "
-			   "(did you forget the %<()%> ?)", member);
+	  {
+	    gcc_rich_location richloc (loc);
+	    /* If "member" has no arguments (other than "this"), then
+	       add a fix-it hint.  */
+	    if (type_num_arguments (TREE_TYPE (member)) == 1)
+	      richloc.add_fixit_insert_after ("()");
+	    emit_diagnostic (diag_kind, &richloc, 0,
+			     "invalid use of member function %qD "
+			     "(did you forget the %<()%> ?)", member);
+	  }
 	else
 	  emit_diagnostic (diag_kind, loc, 0,
 			   "invalid use of member %qD "
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 80ff395..6c40f26 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -105,6 +105,8 @@ extern void inform_n (location_t, unsigned HOST_WIDE_INT, const char *,
 extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern bool emit_diagnostic (diagnostic_t, location_t, int,
 			     const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
+extern bool emit_diagnostic (diagnostic_t, rich_location *, int,
+			     const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
 extern bool emit_diagnostic_valist (diagnostic_t, location_t, int, const char *,
 				    va_list *) ATTRIBUTE_GCC_DIAG (4,0);
 extern bool seen_error (void);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index a572c08..9b583ce 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1168,6 +1168,20 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt,
   return ret;
 }
 
+/* As above, but for rich_location *.  */
+
+bool
+emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
+		 const char *gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, gmsgid);
+  bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, kind);
+  va_end (ap);
+  return ret;
+}
+
 /* Wrapper around diagnostic_impl taking a va_list parameter.  */
 
 bool
diff --git a/gcc/testsuite/g++.dg/parse/missing-parens-fixit.C b/gcc/testsuite/g++.dg/parse/missing-parens-fixit.C
new file mode 100644
index 0000000..a0fd7dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/missing-parens-fixit.C
@@ -0,0 +1,32 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+class t1
+{
+public:
+  double length () const { return m_length; }
+  double area (double width) const { return m_length * width; }
+
+private:
+  double m_length;
+};
+
+bool test_1 (const t1 &inst)
+{
+  return inst.length > 0.0; // { dg-error "did you forget the '\\(\\)'" }
+  /* We expect a fix-it hint.  */
+  /* { dg-begin-multiline-output "" }
+   return inst.length > 0.0;
+          ~~~~~^~~~~~
+                     ()
+     { dg-end-multiline-output "" } */
+}
+
+bool test_2 (const t1 &inst)
+{
+  return inst.area > 0.0; // { dg-error "did you forget the '\\(\\)'" }
+  /* "t1::area" has additional params, so we don't expect a fix-it hint.  */
+  /* { dg-begin-multiline-output "" }
+   return inst.area > 0.0;
+          ~~~~~^~~~
+     { dg-end-multiline-output "" } */
+}
-- 
1.8.5.3



More information about the Gcc-patches mailing list