From ffa87df84a24d715b61da9ea8b920555451f1b7a Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 8 Feb 2019 12:22:41 -0500
Subject: [PATCH 06/63] {NEEDS B&R, CHANGELOG, BLURB; GCC 10 STAGE 1}
 diagnostic-show-locus.c: fix issue with labels (from gcc-git-expr-vs-decl)

---
 gcc/diagnostic-show-locus.c | 62 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 54 insertions(+), 8 deletions(-)

diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index ddc9421..1c04192 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -1406,7 +1406,7 @@ struct line_label
   line_label (int state_idx, int column, label_text text)
   : m_state_idx (state_idx), m_column (column),
     m_text (text), m_length (strlen (text.m_buffer)),
-    m_label_line (0)
+    m_label_line (0), m_has_vbar (true)
   {}
 
   /* Sorting is primarily by column, then by state index.  */
@@ -1425,6 +1425,7 @@ struct line_label
   label_text m_text;
   size_t m_length;
   int m_label_line;
+  bool m_has_vbar;
 };
 
 /* Print any labels in this row.  */
@@ -1512,7 +1513,15 @@ layout::print_any_labels (linenum_type row)
       {
 	/* Would this label "touch" or overlap the next label?  */
 	if (label->m_column + label->m_length >= (size_t)next_column)
-	  max_label_line++;
+	  {
+	    max_label_line++;
+
+	    /* If we've already seen labels with the same column, suppress the
+	       vertical bar for subsequent ones in this backwards iteration;
+	       hence only the one with the highest label_line has m_has_vbar set.  */
+	    if (label->m_column == next_column)
+	      label->m_has_vbar = false;
+	  }
 
 	label->m_label_line = max_label_line;
 	next_column = label->m_column;
@@ -1523,10 +1532,6 @@ layout::print_any_labels (linenum_type row)
      either a vertical bar ('|') for the labels that are lower down, or the
      labels themselves once we've reached their line.  */
   {
-    /* Keep track of in which column we last printed a vertical bar.
-       This allows us to suppress duplicate vertical bars for the case
-       where multiple labels are on one column.  */
-    int last_vbar = 0;
     for (int label_line = 0; label_line <= max_label_line; label_line++)
       {
 	start_annotation_line ();
@@ -1548,14 +1553,13 @@ layout::print_any_labels (linenum_type row)
 		m_colorizer.set_normal_text ();
 		column += label->m_length;
 	      }
-	    else if (label->m_column != last_vbar)
+	    else if (label->m_has_vbar)
 	      {
 		gcc_assert (column <= label->m_column);
 		move_to_column (&column, label->m_column, true);
 		m_colorizer.set_range (label->m_state_idx);
 		pp_character (m_pp, '|');
 		m_colorizer.set_normal_text ();
-		last_vbar = column;
 		column++;
 	      }
 	  }
@@ -2773,6 +2777,48 @@ test_one_liner_labels ()
 		  pp_formatted_text (dc.printer));
   }
 
+  /* Example of out-of-order ranges (thus requiring a sort), where
+     they overlap, and there are multiple ranges on the same point.  */
+  {
+    text_range_label label_0a ("label 0a");
+    text_range_label label_1a ("label 1a");
+    text_range_label label_2a ("label 2a");
+    text_range_label label_0b ("label 0b");
+    text_range_label label_1b ("label 1b");
+    text_range_label label_2b ("label 2b");
+    text_range_label label_0c ("label 0c");
+    text_range_label label_1c ("label 1c");
+    text_range_label label_2c ("label 2c");
+    gcc_rich_location richloc (field, &label_0a);
+    richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1a);
+    richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2a);
+
+    richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0b);
+    richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1b);
+    richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2b);
+
+    richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0c);
+    richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1c);
+    richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2c);
+
+    test_diagnostic_context dc;
+    diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+    ASSERT_STREQ ("\n"
+		  " foo = bar.field;\n"
+		  " ~~~   ~~~ ^~~~~\n"
+		  " |     |   |\n"
+		  " |     |   label 0c\n"
+		  " |     |   label 0b\n"
+		  " |     |   label 0a\n"
+		  " |     label 1c\n"
+		  " |     label 1b\n"
+		  " |     label 1a\n"
+		  " label 2c\n"
+		  " label 2b\n"
+		  " label 2a\n",
+		  pp_formatted_text (dc.printer));
+  }
+
   /* Verify that a NULL result from range_label::get_text is
      handled gracefully.  */
   {
-- 
1.8.5.3

