diff gcc/gcc-rich-location.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/gcc-rich-location.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/gcc-rich-location.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Implementation of gcc_rich_location class
-   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   Copyright (C) 2014-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -38,24 +38,26 @@
 #include "cpplib.h"
 #include "diagnostic.h"
 
-/* Add a range to the rich_location, covering expression EXPR. */
+/* Add a range to the rich_location, covering expression EXPR,
+   using LABEL if non-NULL. */
 
 void
-gcc_rich_location::add_expr (tree expr)
+gcc_rich_location::add_expr (tree expr, range_label *label)
 {
   gcc_assert (expr);
 
   if (CAN_HAVE_RANGE_P (expr))
-    add_range (EXPR_LOCATION (expr), false);
+    add_range (EXPR_LOCATION (expr), SHOW_RANGE_WITHOUT_CARET, label);
 }
 
-/* If T is an expression, add a range for it to the rich_location.  */
+/* If T is an expression, add a range for it to the rich_location,
+   using LABEL if non-NULL. */
 
 void
-gcc_rich_location::maybe_add_expr (tree t)
+gcc_rich_location::maybe_add_expr (tree t, range_label *label)
 {
   if (EXPR_P (t))
-    add_expr (t);
+    add_expr (t, label);
 }
 
 /* Add a fixit hint suggesting replacing the range at MISSPELLED_TOKEN_LOC
@@ -69,3 +71,114 @@
 
   add_fixit_replace (misspelled_token_loc, IDENTIFIER_POINTER (hint_id));
 }
+
+/* Return true if there is nothing on LOC's line before LOC.  */
+
+static bool
+blank_line_before_p (location_t loc)
+{
+  expanded_location exploc = expand_location (loc);
+  char_span line = location_get_source_line (exploc.file, exploc.line);
+  if (!line)
+    return false;
+  if (line.length () < (size_t)exploc.column)
+    return false;
+  /* Columns are 1-based.  */
+  for (int column = 1; column < exploc.column; ++column)
+    if (!ISSPACE (line[column - 1]))
+      return false;
+  return true;
+}
+
+/* Subroutine of gcc_rich_location::add_fixit_insert_formatted.
+   Return true if we should add the content on its own line,
+   false otherwise.
+   If true is returned then *OUT_START_OF_LINE is written to.  */
+
+static bool
+use_new_line (location_t insertion_point, location_t indent,
+	      location_t *out_start_of_line)
+{
+  if (indent == UNKNOWN_LOCATION)
+    return false;
+  const line_map *indent_map = linemap_lookup (line_table, indent);
+  if (linemap_macro_expansion_map_p (indent_map))
+    return false;
+
+  if (!blank_line_before_p (insertion_point))
+    return false;
+
+  /* Locate the start of the line containing INSERTION_POINT.  */
+  const line_map *insertion_point_map
+    = linemap_lookup (line_table, insertion_point);
+  if (linemap_macro_expansion_map_p (insertion_point_map))
+    return false;
+  const line_map_ordinary *ordmap
+    = linemap_check_ordinary (insertion_point_map);
+  expanded_location exploc_insertion_point = expand_location (insertion_point);
+  location_t start_of_line
+    = linemap_position_for_line_and_column (line_table, ordmap,
+					    exploc_insertion_point.line, 1);
+  *out_start_of_line = start_of_line;
+  return true;
+}
+
+/* Add a fix-it hint suggesting the insertion of CONTENT before
+   INSERTION_POINT.
+
+   Attempt to handle formatting: if INSERTION_POINT is the first thing on
+   its line, and INDENT is sufficiently sane, then add CONTENT on its own
+   line, using the indentation of INDENT.
+   Otherwise, add CONTENT directly before INSERTION_POINT.
+
+   For example, adding "CONTENT;" with the closing brace as the insertion
+   point and "INDENT;" as the indentation point:
+
+   if ()
+     {
+       INDENT;
+     }
+
+  would lead to:
+
+   if ()
+     {
+       INDENT;
+       CONTENT;
+     }
+
+  but adding it to:
+
+    if () {INDENT;}
+
+  would lead to:
+
+    if () {INDENT;CONTENT;}
+*/
+
+void
+gcc_rich_location::add_fixit_insert_formatted (const char *content,
+					       location_t insertion_point,
+					       location_t indent)
+{
+  location_t start_of_line;
+  if (use_new_line (insertion_point, indent, &start_of_line))
+    {
+      /* Add CONTENT on its own line, using the indentation of INDENT.  */
+
+      /* Generate an insertion string, indenting by the amount INDENT
+	 was indented.  */
+      int indent_column = LOCATION_COLUMN (get_start (indent));
+      pretty_printer tmp_pp;
+      pretty_printer *pp = &tmp_pp;
+      /* Columns are 1-based.  */
+      for (int column = 1; column < indent_column; ++column)
+	pp_space (pp);
+      pp_string (pp, content);
+      pp_newline (pp);
+
+      add_fixit_insert_before (start_of_line, pp_formatted_text (pp));
+    }
+  else
+    add_fixit_insert_before (insertion_point, content);
+}