From 6ef513de641b2990438b5760184472d62b4390f1 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 2 Sep 2015 10:20:25 -0400
Subject: [PATCH 26/67] FIXME: gcc-rich-location.[ch]: add methods for working
 with tree ranges (compiles, no ChangeLog)

---
 gcc/gcc-rich-location.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/gcc-rich-location.h | 25 +++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
index 98f0f9d..7bda5b0 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -41,6 +41,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "cpplib.h"
 #include "diagnostic.h"
 
+static bool
+get_range_for_expr (tree expr, location_range *r)
+{
+  if (EXPR_HAS_RANGE (expr))
+    {
+      source_range sr = EXPR_LOCATION_RANGE (expr);
+
+      /* Do we have meaningful data?  */
+      if (sr.m_start && sr.m_finish)
+	{
+	  r->m_start = expand_location (sr.m_start);
+	  r->m_finish = expand_location (sr.m_finish);
+	  return true;
+	}
+    }
+
+  return false;
+}
+
 void
 gcc_rich_location::add_range_with_caption (location_t start, location_t finish,
 					   diagnostic_context *context,
@@ -58,6 +77,83 @@ gcc_rich_location::add_range_with_caption (location_t start, location_t finish,
   va_end (ap);
 }
 
+/* Add a range to the rich_location, covering expression EXPR. */
+
+void
+gcc_rich_location::add_expr (tree expr)
+{
+  gcc_assert (expr);
+
+  location_range r;
+  r.m_caption = NULL;
+  r.m_show_caret_p = false;
+  if (get_range_for_expr (expr, &r))
+    add_range (&r);
+}
+
+/* If T is an expression, add a range for it to the rich_location.  */
+
+void
+gcc_rich_location::maybe_add_expr (tree t)
+{
+  if (EXPR_P (t))
+    add_expr (t);
+}
+
+/* As per rich_location::add_expr, but adding a caption to the
+   resulting range.  */
+
+void
+gcc_rich_location::add_expr_with_caption_va (tree expr,
+					     diagnostic_context *context,
+					     const char *gmsgid, va_list *args)
+{
+  gcc_assert (expr);
+  gcc_assert (context);
+  gcc_assert (gmsgid);
+
+  location_range r;
+  r.m_caption = NULL;
+  if (get_range_for_expr (expr, &r))
+    {
+      /* We want to save the string information for later replay.
+	 The printer->format_decoder machinery assumes that we're working
+	 directly from va_args.  It's not possible to save a va_args
+	 for later reuse, since it makes use of a specific stack frame
+	 which needs to still be around.
+	 Hence we need to expand the formatting now, and save the result.  */
+
+      r.m_caption = expand_caption_va (context, gmsgid, args);
+      r.m_show_caret_p = false;
+      add_range (&r); /* This takes ownership of r.m_caption.  */
+    }
+}
+
+void
+gcc_rich_location::add_expr_with_caption (tree expr,
+					  diagnostic_context *context,
+					  const char *gmsgid, ...)
+{
+  va_list ap;
+  va_start (ap, gmsgid);
+  add_expr_with_caption_va (expr, context, gmsgid, &ap);
+  va_end (ap);
+}
+
+void
+gcc_rich_location::maybe_add_expr_with_caption (tree expr,
+						diagnostic_context *context,
+						const char *gmsgid, ...)
+{
+  if (!EXPR_P (expr))
+    return;
+
+  va_list ap;
+  va_start (ap, gmsgid);
+  add_expr_with_caption_va (expr, context, gmsgid, &ap);
+  va_end (ap);
+}
+
 /* FIXME.  */
 
 char *
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 795b60f..a7822ac 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -44,6 +44,31 @@ class gcc_rich_location : public rich_location
 			  const char *gmsgid, ...)
     ATTRIBUTE_GCC_DIAG(5,6);
 
+  /* Methods for adding ranges via gcc entities.  */
+  void
+  add_expr (tree expr);
+
+  void
+  maybe_add_expr (tree t);
+
+  void
+  add_expr_with_caption_va (tree expr,
+			    diagnostic_context *context,
+			    const char *gmsgid, va_list *args)
+    ATTRIBUTE_GCC_DIAG(4, 0);
+
+  void
+  add_expr_with_caption (tree expr,
+			 diagnostic_context *context,
+			 const char *gmsgid, ...)
+    ATTRIBUTE_GCC_DIAG(4,5);
+
+  void
+  maybe_add_expr_with_caption (tree expr,
+			       diagnostic_context *context,
+			       const char *gmsgid, ...)
+    ATTRIBUTE_GCC_DIAG(4,5);
+
  private:
   static char *
   expand_caption_va (diagnostic_context *context,
-- 
1.8.5.3

