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]

[PATCH 4/4] Add -fdiagnostics-generate-patch and -fdiagnostics-apply-fixits


This patch uses the edit_context machinery to provide two new options:

  -fdiagnostics-generate-patch
  -fdiagnostics-apply-fixits

If either is set, an edit_context is created for global_dc, and any
fix-it hints emitted by diagnostics are added to the edit_context.

-fdiagnostics-generate-patch writes out a patch to stderr in unified
diff format.  This is potentially color-coded, following the same rules
as for diagnostics (and affected by -fdiagnostics-color).  The color
scheme mimics that of git-diff.

-fdiagnostics-apply-fixits makes the changes to the filesystem, writing
back to the user's source code.

gcc/ChangeLog:
	* common.opt (fdiagnostics-apply-fixits): New option.
	(fdiagnostics-generate-patch): New option.
	* diagnostic.c: Include "edit-context.h".
	(diagnostic_initialize): Initialize context->edit_context_ptr.
	(diagnostic_finish): Delete context->edit_context_ptr.
	(diagnostic_report_diagnostic): Add fix-it hints from the
	diagnostic to context->edit_context_ptr, if any.
	* diagnostic.h (class edit_context): Add forward decl.
	(struct diagnostic_context): Add field "edit_context_ptr".
	* doc/invoke.texi (Diagnostic Message Formatting Options): Add
	-fdiagnostics-apply-fixits and -fdiagnostics-generate-patch.
	(-fdiagnostics-apply-fixits): New item.
	(-fdiagnostics-generate-patch): New item.
	* toplev.c: Include "edit-context.h".
	(process_options): Set global_dc->edit_context_ptr to a new
	edit_context if the options need one.
	(toplev::main): Handle -fdiagnostics-apply-fixits and
	-fdiagnostics-generate-patch by using global_dc->edit_context_ptr.

gcc/testsuite/ChangeLog:
	* gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c: New
	test case.
	* gcc.dg/plugin/plugin.exp (plugin_test_list): Add
	diagnostic-test-show-locus-generate-patch.c to the sources
	for diagnostic_plugin_test_show_locus.c.
---
 gcc/common.opt                                     |  8 +++
 gcc/diagnostic.c                                   | 11 ++++
 gcc/diagnostic.h                                   |  7 ++
 gcc/doc/invoke.texi                                | 28 +++++++-
 .../diagnostic-test-show-locus-generate-patch.c    | 77 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/plugin/plugin.exp             |  3 +-
 gcc/toplev.c                                       | 20 ++++++
 7 files changed, 152 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c

diff --git a/gcc/common.opt b/gcc/common.opt
index 65a9762..3c7f8bb 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1147,6 +1147,10 @@ fdevirtualize
 Common Report Var(flag_devirtualize) Optimization
 Try to convert virtual calls to direct ones.
 
+fdiagnostics-apply-fixits
+Common Var(flag_diagnostics_apply_fixits)
+Apply fix-it hints to source code, writing back to input files.
+
 fdiagnostics-show-location=
 Common Joined RejectNegative Enum(diagnostic_prefixing_rule)
 -fdiagnostics-show-location=[once|every-line]	How often to emit source location at the beginning of line-wrapped diagnostics.
@@ -1196,6 +1200,10 @@ fdiagnostics-parseable-fixits
 Common Var(flag_diagnostics_parseable_fixits)
 Print fixit hints in machine-readable form.
 
+fdiagnostics-generate-patch
+Common Var(flag_diagnostics_generate_patch)
+Print fix-it hints to stderr in unified diff format.
+
 fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that controls them.
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index b47da38..5a2c565 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "backtrace.h"
 #include "diagnostic.h"
 #include "diagnostic-color.h"
+#include "edit-context.h"
 #include "selftest.h"
 
 #ifdef HAVE_TERMIOS_H
@@ -174,6 +175,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
   context->colorize_source_p = false;
   context->show_ruler_p = false;
   context->parseable_fixits_p = false;
+  context->edit_context_ptr = NULL;
 }
 
 /* Maybe initialize the color support. We require clients to do this
@@ -235,6 +237,12 @@ diagnostic_finish (diagnostic_context *context)
   context->printer->~pretty_printer ();
   XDELETE (context->printer);
   context->printer = NULL;
+
+  if (context->edit_context_ptr)
+    {
+      delete context->edit_context_ptr;
+      context->edit_context_ptr = NULL;
+    }
 }
 
 /* Initialize DIAGNOSTIC, where the message MSG has already been
@@ -943,6 +951,9 @@ diagnostic_report_diagnostic (diagnostic_context *context,
   diagnostic->message.format_spec = saved_format_spec;
   diagnostic->x_data = NULL;
 
+  if (context->edit_context_ptr)
+    context->edit_context_ptr->add_fixits (diagnostic->richloc);
+
   context->lock--;
 
   return true;
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 104e39c..5752563 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -62,6 +62,8 @@ typedef void (*diagnostic_start_span_fn) (diagnostic_context *,
 
 typedef diagnostic_starter_fn diagnostic_finalizer_fn;
 
+class edit_context;
+
 /* This data structure bundles altogether any information relevant to
    the context of a diagnostic message.  */
 struct diagnostic_context
@@ -209,6 +211,11 @@ struct diagnostic_context
   /* If true, print fixits in machine-parseable form after the
      rest of the diagnostic.  */
   bool parseable_fixits_p;
+
+  /* If non-NULL, an edit_context to which fix-it hints should be
+     applied, for generating patches or writing back changes to
+     source code.  */
+  edit_context *edit_context_ptr;
 };
 
 static inline void
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1f04501..bb65dae 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -248,7 +248,8 @@ Objective-C and Objective-C++ Dialects}.
 -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]}  @gol
 -fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]}  @gol
 -fno-diagnostics-show-option -fno-diagnostics-show-caret @gol
--fdiagnostics-parseable-fixits}
+-fdiagnostics-parseable-fixits @gol
+-fdiagnostics-apply-fixits -fdiagnostics-generate-patch}
 
 @item Warning Options
 @xref{Warning Options,,Options to Request or Suppress Warnings}.
@@ -3428,6 +3429,31 @@ An empty replacement string indicates that the given range is to be removed.
 An empty range (e.g. ``45:3-45:3'') indicates that the string is to
 be inserted at the given position.
 
+@item -fdiagnostics-apply-fixits
+@opindex fdiagnostics-apply-fixits
+Apply fix-it hints to source code, writing back to input files.
+
+@item -fdiagnostics-generate-patch
+@opindex fdiagnostics-generate-patch
+Print fix-it hints to stderr in unified diff format, after any diagnostics
+are printed.  For example:
+
+@smallexample
+--- test.c
++++ test.c
+@@ -42,5 +42,5 @@
+
+ void show_cb(GtkDialog *dlg)
+ @{
+-  gtk_widget_showall(dlg);
++  gtk_widget_show_all(dlg);
+ @}
+
+@end smallexample
+
+The diff may or may not be colorized, following the same rules
+as for diagnostics (see @option{-fdiagnostics-color}).
+
 @end table
 
 @node Warning Options
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
new file mode 100644
index 0000000..afbaf63
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
@@ -0,0 +1,77 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-generate-patch" } */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+   see the overview in diagnostic_plugin_test_show_locus.c.
+
+   In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+   and that we can't use macros in this file.  */
+
+/* Unit test for rendering of insertion fixit hints
+   (example taken from PR 62316).  */
+
+void test_fixit_insert (void)
+{
+#if 0
+   int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
+#endif
+}
+
+/* Unit test for rendering of "remove" fixit hints.  */
+
+void test_fixit_remove (void)
+{
+#if 0
+  int a;; /* { dg-warning "example of a removal hint" } */
+#endif
+}
+
+/* Unit test for rendering of "replace" fixit hints.  */
+
+void test_fixit_replace (void)
+{
+#if 0
+  gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" } */
+#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.  */
+
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+
+/* Next, we expect the diff itself.  */
+/* { dg-begin-multiline-output "" }
+@@ -14,7 +14,7 @@
+ void test_fixit_insert (void)
+ {
+ #if 0
+-   int a[2][2] = { 0, 1 , 2, 3 };
++   int a[2][2] = { {0, 1} , 2, 3 };
+ #endif
+ }
+ 
+@@ -23,7 +23,7 @@
+ void test_fixit_remove (void)
+ {
+ #if 0
+-  int a;;
++  int a;
+ #endif
+ }
+ 
+@@ -32,7 +32,7 @@
+ void test_fixit_replace (void)
+ {
+ #if 0
+-  gtk_widget_showall (dlg);
++  gtk_widget_show_all (dlg);
+ #endif
+ }
+ 
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 715038a..32ca748 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -65,7 +65,8 @@ set plugin_test_list [list \
     { diagnostic_plugin_test_show_locus.c \
 	  diagnostic-test-show-locus-bw.c \
 	  diagnostic-test-show-locus-color.c \
-	  diagnostic-test-show-locus-parseable-fixits.c } \
+	  diagnostic-test-show-locus-parseable-fixits.c \
+	  diagnostic-test-show-locus-generate-patch.c } \
     { diagnostic_plugin_test_tree_expression_range.c \
 	  diagnostic-test-expressions-1.c } \
     { diagnostic_plugin_show_trees.c \
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 2607904..5a613b8 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -76,6 +76,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-chkp.h"
 #include "omp-low.h"
 #include "hsa.h"
+#include "edit-context.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
@@ -1221,6 +1222,9 @@ process_options (void)
   /* Some machines may reject certain combinations of options.  */
   targetm.target_option.override ();
 
+  if (flag_diagnostics_generate_patch || flag_diagnostics_apply_fixits)
+      global_dc->edit_context_ptr = new edit_context ();
+
   /* Avoid any informative notes in the second run of -fcompare-debug.  */
   if (flag_compare_debug) 
     diagnostic_inhibit_notes (global_dc);
@@ -2147,6 +2151,22 @@ toplev::main (int argc, char **argv)
      emit some diagnostics here.  */
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
+  if (flag_diagnostics_generate_patch)
+    {
+      gcc_assert (global_dc->edit_context_ptr);
+
+      pretty_printer (pp);
+      pp_show_color (&pp) = pp_show_color (global_dc->printer);
+      global_dc->edit_context_ptr->print_diff (&pp, true);
+      pp_flush (&pp);
+    }
+
+  if (flag_diagnostics_apply_fixits)
+    {
+      gcc_assert (global_dc->edit_context_ptr);
+      global_dc->edit_context_ptr->apply_changes ();
+    }
+
   diagnostic_finish (global_dc);
 
   finalize_plugins ();
-- 
1.8.5.3


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