Allow the use of ad-hoc locations for fix-it hints
authorDavid Malcolm <dmalcolm@redhat.com>
Mon, 29 Aug 2016 20:42:57 +0000 (20:42 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Mon, 29 Aug 2016 20:42:57 +0000 (20:42 +0000)
Currently the fix-it validator rejects ad-hoc locations.
Fix this by calling get_pure_location on the input locations to
add_fixit_insert/replace.  Doing so requires moving get_pure_location
from gcc to libcpp.

gcc/ChangeLog:
* diagnostic-show-locus.c
(selftest::test_one_liner_fixit_validation_adhoc_locations): New
function.
(selftest::test_diagnostic_show_locus_one_liner): Call it.
* input.c (get_pure_location): Move to libcpp/line-map.c.
* input.h (get_pure_location): Convert decl to an inline function
calling implementation in libcpp.

libcpp/ChangeLog:
* include/line-map.h (get_pure_location): New decl.
* line-map.c (get_pure_location): Move here, from gcc/input.c, adding
a line_maps * param.
(rich_location::add_fixit_insert): Call get_pure_location on "where".
(rich_location::add_fixit_replace): Call get_pure_location on the
end-points.

From-SVN: r239843

gcc/ChangeLog
gcc/diagnostic-show-locus.c
gcc/input.c
gcc/input.h
libcpp/ChangeLog
libcpp/include/line-map.h
libcpp/line-map.c

index 065b9a33c195e639d9be792d6f3de26c97410384..478351818c2f006abd9b046f5e062e5c6a15a583 100644 (file)
@@ -1,3 +1,13 @@
+2016-08-29  David Malcolm  <dmalcolm@redhat.com>
+
+       * diagnostic-show-locus.c
+       (selftest::test_one_liner_fixit_validation_adhoc_locations): New
+       function.
+       (selftest::test_diagnostic_show_locus_one_liner): Call it.
+       * input.c (get_pure_location): Move to libcpp/line-map.c.
+       * input.h (get_pure_location): Convert decl to an inline function
+       calling implementation in libcpp.
+
 2016-08-29  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/77403
index f3f661ee6926afc986c6903375a7b5fbfc8d3370..ba52f24778a9a97aa164e1baba970b8f87f8980c 100644 (file)
@@ -1594,6 +1594,75 @@ test_one_liner_fixit_replace_equal_secondary_range ()
                pp_formatted_text (dc.printer));
 }
 
+/* Verify that we can use ad-hoc locations when adding fixits to a
+   rich_location.  */
+
+static void
+test_one_liner_fixit_validation_adhoc_locations ()
+{
+  /* Generate a range that's too long to be packed, so must
+     be stored as an ad-hoc location (given the defaults
+     of 5 bits or 0 bits of packed range); 41 columns > 2**5.  */
+  const location_t c7 = linemap_position_for_column (line_table, 7);
+  const location_t c47 = linemap_position_for_column (line_table, 47);
+  const location_t loc = make_location (c7, c7, c47);
+
+  if (c47 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+    return;
+
+  ASSERT_TRUE (IS_ADHOC_LOC (loc));
+
+  /* Insert.  */
+  {
+    rich_location richloc (line_table, loc);
+    richloc.add_fixit_insert (loc, "test");
+    /* It should not have been discarded by the validator.  */
+    ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+    test_diagnostic_context dc;
+    diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+    ASSERT_STREQ ("\n"
+                 " foo = bar.field;\n"
+                 "       ^~~~~~~~~~                               \n"
+                 "       test\n",
+                 pp_formatted_text (dc.printer));
+  }
+
+  /* Remove.  */
+  {
+    rich_location richloc (line_table, loc);
+    source_range range = source_range::from_locations (loc, c47);
+    richloc.add_fixit_remove (range);
+    /* It should not have been discarded by the validator.  */
+    ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+    test_diagnostic_context dc;
+    diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+    ASSERT_STREQ ("\n"
+                 " foo = bar.field;\n"
+                 "       ^~~~~~~~~~                               \n"
+                 "       -----------------------------------------\n",
+                 pp_formatted_text (dc.printer));
+  }
+
+  /* Replace.  */
+  {
+    rich_location richloc (line_table, loc);
+    source_range range = source_range::from_locations (loc, c47);
+    richloc.add_fixit_replace (range, "test");
+    /* It should not have been discarded by the validator.  */
+    ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+    test_diagnostic_context dc;
+    diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+    ASSERT_STREQ ("\n"
+                 " foo = bar.field;\n"
+                 "       ^~~~~~~~~~                               \n"
+                 "       test\n",
+                 pp_formatted_text (dc.printer));
+  }
+}
+
 /* Run the various one-liner tests.  */
 
 static void
@@ -1626,6 +1695,7 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_)
   test_one_liner_fixit_replace ();
   test_one_liner_fixit_replace_non_equal_range ();
   test_one_liner_fixit_replace_equal_secondary_range ();
+  test_one_liner_fixit_validation_adhoc_locations ();
 }
 
 /* Verify that fix-it hints are appropriately consolidated.
index 4ec218d52a4d8f2e495fc3a54b6992d8382384ac..a3fe54209dd327a2e644a056d3dd4c67d5b7aafa 100644 (file)
@@ -838,28 +838,6 @@ expansion_point_location (source_location location)
                                   LRK_MACRO_EXPANSION_POINT, NULL);
 }
 
-/* Given location LOC, strip away any packed range information
-   or ad-hoc information.  */
-
-location_t
-get_pure_location (location_t loc)
-{
-  if (IS_ADHOC_LOC (loc))
-    loc
-      = line_table->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
-
-  if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
-    return loc;
-
-  if (loc < RESERVED_LOCATION_COUNT)
-    return loc;
-
-  const line_map *map = linemap_lookup (line_table, loc);
-  const line_map_ordinary *ordmap = linemap_check_ordinary (map);
-
-  return loc & ~((1 << ordmap->m_range_bits) - 1);
-}
-
 /* Construct a location with caret at CARET, ranging from START to
    finish e.g.
 
index ecf8db3a7ea58d5e8aa6cdcc3d680daa93bafb97..fd21f34abf15d663aecb87e6c6fb8bf3cdeaf3ab 100644 (file)
@@ -77,7 +77,11 @@ extern location_t input_location;
 #define from_macro_expansion_at(LOC) \
   ((linemap_location_from_macro_expansion_p (line_table, LOC)))
 
-extern location_t get_pure_location (location_t loc);
+static inline location_t
+get_pure_location (location_t loc)
+{
+  return get_pure_location (line_table, loc);
+}
 
 /* Get the start of any range encoded within location LOC.  */
 
index 56971ad8e0cda00e6482dd26de96ae88ccd5b343..37825f524d35cd47e7c07c0607a0a03e15130ed6 100644 (file)
@@ -1,3 +1,12 @@
+2016-08-26  David Malcolm  <dmalcolm@redhat.com>
+
+       * include/line-map.h (get_pure_location): New decl.
+       * line-map.c (get_pure_location): Move here, from gcc/input.c, adding
+       a line_maps * param.
+       (rich_location::add_fixit_insert): Call get_pure_location on "where".
+       (rich_location::add_fixit_replace): Call get_pure_location on the
+       end-points.
+
 2016-08-26  David Malcolm  <dmalcolm@redhat.com>
 
        * include/line-map.h (rich_location): Eliminate unimplemented
index 0fc4848bf5b0ed2e89785af3100f1273ac9b3a0e..d9c31deb9772f2c8749946755974edfc009dc6bb 100644 (file)
@@ -1002,6 +1002,12 @@ IS_ADHOC_LOC (source_location loc)
 bool
 pure_location_p (line_maps *set, source_location loc);
 
+/* Given location LOC within SET, strip away any packed range information
+   or ad-hoc information.  */
+
+extern source_location get_pure_location (line_maps *set,
+                                         source_location loc);
+
 /* Combine LOC and BLOCK, giving a combined adhoc location.  */
 
 inline source_location
index 8fe48bdbf63a63ff57faec5da298c828ebb1761f..f5b15867a62190131e94fb598aa69eef63f74df0 100644 (file)
@@ -311,6 +311,28 @@ pure_location_p (line_maps *set, source_location loc)
   return true;
 }
 
+/* Given location LOC within SET, strip away any packed range information
+   or ad-hoc information.  */
+
+source_location
+get_pure_location (line_maps *set, source_location loc)
+{
+  if (IS_ADHOC_LOC (loc))
+    loc
+      = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+
+  if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
+    return loc;
+
+  if (loc < RESERVED_LOCATION_COUNT)
+    return loc;
+
+  const line_map *map = linemap_lookup (set, loc);
+  const line_map_ordinary *ordmap = linemap_check_ordinary (map);
+
+  return loc & ~((1 << ordmap->m_range_bits) - 1);
+}
+
 /* Finalize the location_adhoc_data structure.  */
 void
 location_adhoc_data_fini (struct line_maps *set)
@@ -2077,6 +2099,8 @@ void
 rich_location::add_fixit_insert (source_location where,
                                 const char *new_content)
 {
+  where = get_pure_location (m_line_table, where);
+
   if (reject_impossible_fixit (where))
     return;
 
@@ -2141,6 +2165,9 @@ rich_location::add_fixit_replace (source_range src_range,
 {
   linemap_assert (m_num_fixit_hints < MAX_FIXIT_HINTS);
 
+  src_range.m_start = get_pure_location (m_line_table, src_range.m_start);
+  src_range.m_finish = get_pure_location (m_line_table, src_range.m_finish);
+
   if (reject_impossible_fixit (src_range.m_start))
     return;
   if (reject_impossible_fixit (src_range.m_finish))