From e197abea5db75e35a0d097b27c3e9bf69cee0074 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 16 Oct 2015 15:11:25 -0400
Subject: [PATCH 17/49] Delay some resolution of ad-hoc locations, preserving
 ranges

Some diagnostics e.g. -Wmaybe-uninitialized weren't showing
underlines, despite being provided with range-based data.

Debugging showed that it the pertinent location was an
ad-hoc location with a range:

  (gdb) p /x loc
  $9 = 0x8000002a

  (gdb) p line_table->location_adhoc_data_map.data[0x2a]
  $10 = {locus = 6919936, src_range = {m_start = 6919936,
         m_finish = 6921216}, data = 0x7ffff19a8480}

  (gdb) call inform (loc, "foo")
  test.c: In function 'test':
  test.c:173:10: note: foo
  return result;
         ^~~~~~

but the result from linemap_resolve_location here:

  location = linemap_resolve_location (line_table, location,
                                       LRK_SPELLING_LOCATION,
                                       NULL);

was stripping away the ad-hoc location to just the locus:

  Value returned is $11 = 6919936

at the front of the token, thus losing the underline.

The fix is to rework linemap_resolve_location to avoid bypassing
ad-hoc locations, so that range data is available later.

gcc/testsuite/ChangeLog:
	* gcc.dg/diagnostic-tree-expr-ranges-2.c: New file.

libcpp/ChangeLog:
	* line-map.c (linemap_position_for_loc_and_offset): Handle
	ad-hoc locations.
	(linemap_macro_map_loc_unwind_toward_spelling): Add line_maps
	param.  Handle ad-hoc locations.
	(linemap_location_in_system_header_p): Pass on "set" to call to
	linemap_macro_map_loc_unwind_toward_spelling.
	(linemap_macro_loc_to_spelling_point): Retain ad-hoc locations.
	Pass on "set" to call to
	linemap_macro_map_loc_unwind_toward_spelling.
	(linemap_resolve_location): Retain ad-hoc locations.  Pass on
	"set" to call to linemap_macro_map_loc_unwind_toward_spelling.
	(linemap_unwind_toward_expansion):  Pass on "set" to call to
	linemap_macro_map_loc_unwind_toward_spelling.
---
 .../gcc.dg/diagnostic-tree-expr-ranges-2.c         | 23 ++++++++++++++++++
 libcpp/line-map.c                                  | 28 ++++++++++++----------
 2 files changed, 39 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c

diff --git a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
new file mode 100644
index 0000000..302e233
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -fdiagnostics-show-caret" } */
+
+int test_uninit_1 (void)
+{
+  int result;
+  return result;  /* { dg-warning "uninitialized" } */
+/* { dg-begin-multiline-output "" }
+   return result;
+          ^~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+int test_uninit_2 (void)
+{
+  int result;
+  result += 3; /* { dg-warning "uninitialized" } */
+/* { dg-begin-multiline-output "" }
+   result += 3;
+   ~~~~~~~^~~~
+   { dg-end-multiline-output "" } */
+  return result;
+}
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 2cbd56a..6385fdf 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -46,7 +46,7 @@ static const line_map_macro* linemap_macro_map_lookup (struct line_maps *,
 static source_location linemap_macro_map_loc_to_def_point
 (const line_map_macro *, source_location);
 static source_location linemap_macro_map_loc_unwind_toward_spelling
-(const line_map_macro *, source_location);
+(line_maps *set, const line_map_macro *, source_location);
 static source_location linemap_macro_map_loc_to_exp_point
 (const line_map_macro *, source_location);
 static source_location linemap_macro_loc_to_spelling_point
@@ -687,6 +687,9 @@ linemap_position_for_loc_and_offset (struct line_maps *set,
 {
   const line_map_ordinary * map = NULL;
 
+  if (IS_ADHOC_LOC (loc))
+    loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+
   /* This function does not support virtual locations yet.  */
   if (linemap_assert_fails
       (!linemap_location_from_macro_expansion_p (set, loc)))
@@ -907,14 +910,19 @@ linemap_macro_map_loc_to_def_point (const line_map_macro *map,
    In other words, this returns the xI location presented in the
    comments of line_map_macro above.  */
 source_location
-linemap_macro_map_loc_unwind_toward_spelling (const line_map_macro* map,
+linemap_macro_map_loc_unwind_toward_spelling (line_maps *set,
+					      const line_map_macro* map,
 					      source_location location)
 {
   unsigned token_no;
 
+  if (IS_ADHOC_LOC (location))
+    location = get_location_from_adhoc_loc (set, location);
+
   linemap_assert (linemap_macro_expansion_map_p (map)
 		  && location >= MAP_START_LOCATION (map));
   linemap_assert (location >= RESERVED_LOCATION_COUNT);
+  linemap_assert (!IS_ADHOC_LOC (location));
 
   token_no = location - MAP_START_LOCATION (map);
   linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
@@ -1024,7 +1032,7 @@ linemap_location_in_system_header_p (struct line_maps *set,
 
 	      /* It's a token resulting from a macro expansion.  */
 	      source_location loc =
-		linemap_macro_map_loc_unwind_toward_spelling (macro_map, location);
+		linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, location);
 	      if (loc < RESERVED_LOCATION_COUNT)
 		/* This token might come from a built-in macro.  Let's
 		   look at where that macro got expanded.  */
@@ -1197,11 +1205,6 @@ linemap_macro_loc_to_spelling_point (struct line_maps *set,
 				     const line_map_ordinary **original_map)
 {
   struct line_map *map;
-
-  if (IS_ADHOC_LOC (location))
-    location = set->location_adhoc_data_map.data[location
-						 & MAX_SOURCE_LOCATION].locus;
-
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -1212,7 +1215,7 @@ linemap_macro_loc_to_spelling_point (struct line_maps *set,
 
       location
 	= linemap_macro_map_loc_unwind_toward_spelling
-	    (linemap_check_macro (map),
+	    (set, linemap_check_macro (map),
 	     location);
     }
 
@@ -1355,10 +1358,11 @@ linemap_resolve_location (struct line_maps *set,
 			  enum location_resolution_kind lrk,
 			  const line_map_ordinary **map)
 {
+  source_location locus = loc;
   if (IS_ADHOC_LOC (loc))
-    loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+    locus = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
 
-  if (loc < RESERVED_LOCATION_COUNT)
+  if (locus < RESERVED_LOCATION_COUNT)
     {
       /* A reserved location wasn't encoded in a map.  Let's return a
 	 NULL map here, just like what linemap_ordinary_map_lookup
@@ -1410,7 +1414,7 @@ linemap_unwind_toward_expansion (struct line_maps *set,
     loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
 
   resolved_location =
-    linemap_macro_map_loc_unwind_toward_spelling (macro_map, loc);
+    linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, loc);
   resolved_map = linemap_lookup (set, resolved_location);
 
   if (!linemap_macro_expansion_map_p (resolved_map))
-- 
1.8.5.3

