gcc/ChangeLog:
        * gcc-rich-location.c (get_range_for_expr): New function.
        (gcc_rich_location::add_expr): New method.
        (gcc_rich_location::maybe_add_expr): New method.
        (gcc_rich_location::add_expr_with_caption_va): New method.
        (gcc_rich_location::add_expr_with_caption): New method.
        (gcc_rich_location::maybe_add_expr_with_caption): New method.
        * gcc-rich-location.h (gcc_rich_location::add_expr): New method.
        (gcc_rich_location::maybe_add_expr): New method.
        (gcc_rich_location::add_expr_with_caption_va): New method.
        (gcc_rich_location::add_expr_with_caption): New method.
        (gcc_rich_location::maybe_add_expr_with_caption): New method.
---
 gcc/gcc-rich-location.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/gcc-rich-location.h | 25 +++++++++++++
 2 files changed, 124 insertions(+)

diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
index bdb2915..003e8f0 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -41,6 +41,28 @@ along with GCC; see the file COPYING3.  If not see
 #include "cpplib.h"
 #include "diagnostic.h"
 
+/* Extract any source range information from EXPR and write it
+   to *R.  */
+
+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;
+}
+
 /* Add a range covering [START, FINISH], with a caption given
    by translating and formatting GMSGID and any variadic args.  */
 
@@ -61,6 +83,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);
+}
+
 /* Translate and expand the given GMSGID and ARGS into a caption
    (or NULL).
 
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

Reply via email to