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