C++: fix-it hint for missing parentheses
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 30 Nov 2018 22:51:18 +0000 (22:51 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Fri, 30 Nov 2018 22:51:18 +0000 (22:51 +0000)
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.

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.

From-SVN: r266696

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/typeck2.c
gcc/diagnostic-core.h
gcc/diagnostic.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/missing-parens-fixit.C [new file with mode: 0644]

index 58b5886..bda587b 100644 (file)
@@ -1,5 +1,11 @@
 2018-11-30  David Malcolm  <dmalcolm@redhat.com>
 
+       * diagnostic-core.h (emit_diagnostic): New decl.
+       * diagnostic.c (emit_diagnostic): New overload, taking a
+       rich_location *.
+
+2018-11-30  David Malcolm  <dmalcolm@redhat.com>
+
        * pretty-print.c (class selftest::test_pretty_printer): New
        subclass of pretty_printer.
        (selftest::test_prefixes_and_wrapping): New test.
index 2c8b7d1..dbe4ad3 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-30  David Malcolm  <dmalcolm@redhat.com>
+
+       * 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.
+
 2018-11-30  James Norris  <jnorris@codesourcery.com>
 
        * parser.c (cp_parser_oacc_enter_exit_data): Use existing local
index d0b1235..64e36ef 100644 (file)
@@ -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 "
index 80ff395..6c40f26 100644 (file)
@@ -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);
index 1b572ae..d97e959 100644 (file)
@@ -1200,6 +1200,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
index 1c6a956..c5b5513 100644 (file)
@@ -1,3 +1,7 @@
+2018-11-30  David Malcolm  <dmalcolm@redhat.com>
+
+       * g++.dg/parse/missing-parens-fixit.C: New test.
+
 2018-11-30  Michael Ploujnikov  <michael.ploujnikov@oracle.com>
 
        * gcc.dg/independent-cloneids-1.c: New test.
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 (file)
index 0000000..a0fd7dd
--- /dev/null
@@ -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 "" } */
+}