Add support for mutually-incompatible fix-it hints
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 9 Jun 2017 20:57:38 +0000 (20:57 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Fri, 9 Jun 2017 20:57:38 +0000 (20:57 +0000)
This patch adds a method:
  rich_location::fixits_cannot_be_auto_applied
for ensuring that mutually-incompatible fix-its hints don't
lead to insane output from -fdiagnostics-generate-patch.

Fix-it hints within such rich_location instances are printed
as normal by diagnostic_show_locus, but don't affect the output
of -fdiagnostics-generate-patch.

gcc/ChangeLog:
* diagnostic.c (diagnostic_report_diagnostic): Only add fixits
to the edit_context if they can be auto-applied.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic-test-show-locus-bw.c
(test_mutually_exclusive_suggestions): New test function.
* gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
(test_mutually_exclusive_suggestions): New test function.
* gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c
(test_mutually_exclusive_suggestions): New test function.
* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
(test_show_locus): Add special-case for
"test_mutually_exclusive_suggestions".

libcpp/ChangeLog:
* include/line-map.h
(rich_location::fixits_cannot_be_auto_applied): New method.
(rich_location::fixits_can_be_auto_applied_p): New accessor.
(rich_location::m_fixits_cannot_be_auto_applied): New field.
* line-map.c (rich_location::rich_location): Initialize new field.

From-SVN: r249081

gcc/ChangeLog
gcc/diagnostic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
libcpp/ChangeLog
libcpp/include/line-map.h
libcpp/line-map.c

index 9cbae2a09efd9c237ac4495403fd70341b48c101..4ab6f8a168afe770c8d11e24c0211f8127478eef 100644 (file)
@@ -1,3 +1,8 @@
+2017-06-09  David Malcolm  <dmalcolm@redhat.com>
+
+       * diagnostic.c (diagnostic_report_diagnostic): Only add fixits
+       to the edit_context if they can be auto-applied.
+
 2017-06-9  Ian Lance Taylor  <iant@golang.org>
 
        * opts.c (finish_options): If -fsplit-stack, disable implicit
index 158519606f8d1c4570f51a53d979bba0d7cbf5cb..bbf5f5ce7a611e5fba0784bcedd8e35f8115d5c1 100644 (file)
@@ -986,7 +986,8 @@ diagnostic_report_diagnostic (diagnostic_context *context,
   diagnostic->x_data = NULL;
 
   if (context->edit_context_ptr)
-    context->edit_context_ptr->add_fixits (diagnostic->richloc);
+    if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
+      context->edit_context_ptr->add_fixits (diagnostic->richloc);
 
   context->lock--;
 
index 05a5827dca7a4535a2dfc59e24308aaecb260565..cc36d7a35b6c8e760ff97775e0600763f682e399 100644 (file)
@@ -1,3 +1,15 @@
+2017-06-09  David Malcolm  <dmalcolm@redhat.com>
+
+       * gcc.dg/plugin/diagnostic-test-show-locus-bw.c
+       (test_mutually_exclusive_suggestions): New test function.
+       * gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
+       (test_mutually_exclusive_suggestions): New test function.
+       * gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c
+       (test_mutually_exclusive_suggestions): New test function.
+       * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
+       (test_show_locus): Add special-case for
+       "test_mutually_exclusive_suggestions".
+
 2017-06-09  Ian Lance Taylor  <iant@golang.org>
 
        * gcc.dg/tree-prof/split-1.c: New test.
index 25b9d6cb3826d47fd139fee80e06b8a9f6e50ab2..100fa380cd70df22ae4e9d5a715f4102f5758e22 100644 (file)
@@ -269,3 +269,23 @@ void test_fixit_insert_newline (void)
    { dg-end-multiline-output "" } */
 #endif
 }
+
+/* Unit test for mutually-exclusive suggestions.  */
+
+void test_mutually_exclusive_suggestions (void)
+{
+#if 0
+  original; /* { dg-warning "warning 1" } */
+/* { dg-warning "warning 2" "" { target *-*-* } .-1 } */
+/* { dg-begin-multiline-output "" }
+   original;
+   ^~~~~~~~
+   replacement_1
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   original;
+   ^~~~~~~~
+   replacement_2
+   { dg-end-multiline-output "" } */
+#endif
+}
index 4522dcd350e7189aac42b98817021253d0718100..f1963dd20c1e3a8925461f3eb81f62fc23b5ea1d 100644 (file)
@@ -51,6 +51,19 @@ void test_fixit_insert_newline (void)
 #endif
 }
 
+/* Unit test for mutually-exclusive suggestions.  */
+
+void test_mutually_exclusive_suggestions (void)
+{
+#if 0
+  original; /* { dg-warning "warning 1" } */
+/* { dg-warning "warning 2" "" { target *-*-* } .-1 } */
+/* We should not print the mutually-incompatible fix-it hints within
+   the generated patch; they are not listed in the big expected
+   multiline output below.  */
+#endif
+}
+
 /* Verify the output from -fdiagnostics-generate-patch.
    We expect a header, containing the filename.  This is the absolute path,
    so we can only capture it via regexps.  */
index 25a7c3c507216221738b98df5e22c789077e1ae8..16162baeb7ec60cecd093f1508477e3ec0418842 100644 (file)
@@ -55,3 +55,17 @@ void test_fixit_insert_newline (void)
 /* { dg-regexp "fix-it:.*\\{52:1-52:1\\}:.*\\n" } */
 #endif
 }
+
+/* Unit test for mutually-exclusive suggestions.  */
+
+void test_mutually_exclusive_suggestions (void)
+{
+#if 0
+  original; /* { dg-warning "warning 1" } */
+/* { dg-warning "warning 2" "" { target *-*-* } .-1 } */
+/* We should print the mutually-incompatible fix-it hints within
+   -fdiagnostics-parseable-fixits; verify that they are printed.  */
+/* { dg-regexp "fix-it:.*\\{64:3-64:11}:.*\\n" } */
+/* { dg-regexp "fix-it:.*\\{64:3-64:11}:.*\\n" } */
+#endif
+}
index 6afb58414f0b6e80398a47c428165c9ac0d45417..0a8eeba1846d7fa1ae3961867915e98abe547c26 100644 (file)
@@ -306,6 +306,30 @@ test_show_locus (function *fun)
       warning_at_rich_loc (&richloc, 0, "example of a replacement hint");
     }
 
+  if (0 == strcmp (fnname, "test_mutually_exclusive_suggestions"))
+    {
+      const int line = fnstart_line + 2;
+      location_t start = get_loc (line, 2);
+      location_t finish = get_loc (line, 9);
+      source_range src_range;
+      src_range.m_start = start;
+      src_range.m_finish = finish;
+
+      {
+       rich_location richloc (line_table, make_location (start, start, finish));
+       richloc.add_fixit_replace (src_range, "replacement_1");
+       richloc.fixits_cannot_be_auto_applied ();
+       warning_at_rich_loc (&richloc, 0, "warning 1");
+      }
+
+      {
+       rich_location richloc (line_table, make_location (start, start, finish));
+       richloc.add_fixit_replace (src_range, "replacement_2");
+       richloc.fixits_cannot_be_auto_applied ();
+       warning_at_rich_loc (&richloc, 0, "warning 2");
+      }
+    }  
+
   /* Example of two carets where both carets appear to have an off-by-one
      error appearing one column early.
      Seen with gfortran.dg/associate_5.f03.
index 8032d7cde9990602a1601f95461482b5efd63c5c..13a33c302f633f3e8e90344eebaf5f7fe1e1681c 100644 (file)
@@ -1,3 +1,11 @@
+2017-06-09  David Malcolm  <dmalcolm@redhat.com>
+
+       * include/line-map.h
+       (rich_location::fixits_cannot_be_auto_applied): New method.
+       (rich_location::fixits_can_be_auto_applied_p): New accessor.
+       (rich_location::m_fixits_cannot_be_auto_applied): New field.
+       * line-map.c (rich_location::rich_location): Initialize new field.
+
 2017-06-05  David Malcolm  <dmalcolm@redhat.com>
 
        * include/cpplib.h (struct cpp_callbacks): Add "comment"
index 90d65d746ab43df5badd06223c0c7be307ada0ee..be3041df2bec1df50edc45a99b5f995b87fad696 100644 (file)
@@ -1663,6 +1663,27 @@ class rich_location
   fixit_hint *get_last_fixit_hint () const;
   bool seen_impossible_fixit_p () const { return m_seen_impossible_fixit; }
 
+  /* Set this if the fix-it hints are not suitable to be
+     automatically applied.
+
+     For example, if you are suggesting more than one
+     mutually exclusive solution to a problem, then
+     it doesn't make sense to apply all of the solutions;
+     manual intervention is required.
+
+     If set, then the fix-it hints in the rich_location will
+     be printed, but will not be added to generated patches,
+     or affect the modified version of the file.  */
+  void fixits_cannot_be_auto_applied ()
+  {
+    m_fixits_cannot_be_auto_applied = true;
+  }
+
+  bool fixits_can_be_auto_applied_p () const
+  {
+    return !m_fixits_cannot_be_auto_applied;
+  }
+
 private:
   bool reject_impossible_fixit (source_location where);
   void stop_supporting_fixits ();
@@ -1686,6 +1707,7 @@ protected:
   semi_embedded_vec <fixit_hint *, MAX_STATIC_FIXIT_HINTS> m_fixit_hints;
 
   bool m_seen_impossible_fixit;
+  bool m_fixits_cannot_be_auto_applied;
 };
 
 /* A fix-it hint: a suggested insertion, replacement, or deletion of text.
index c4b7cb2365126d51bc5ad861eba41c6ee807555a..5caaf6b2d68472c29a680ee1dfe7d3455a44910c 100644 (file)
@@ -2012,7 +2012,8 @@ rich_location::rich_location (line_maps *set, source_location loc) :
   m_column_override (0),
   m_have_expanded_location (false),
   m_fixit_hints (),
-  m_seen_impossible_fixit (false)
+  m_seen_impossible_fixit (false),
+  m_fixits_cannot_be_auto_applied (false)
 {
   add_range (loc, true);
 }