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