/* JSON output for diagnostics
- Copyright (C) 2018-2020 Free Software Foundation, Inc.
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "diagnostic.h"
+#include "selftest-diagnostic.h"
#include "diagnostic-metadata.h"
#include "json.h"
#include "selftest.h"
/* Generate a JSON object for LOC. */
json::value *
-json_from_expanded_location (location_t loc)
+json_from_expanded_location (diagnostic_context *context, location_t loc)
{
expanded_location exploc = expand_location (loc);
json::object *result = new json::object ();
if (exploc.file)
result->set ("file", new json::string (exploc.file));
result->set ("line", new json::integer_number (exploc.line));
- result->set ("column", new json::integer_number (exploc.column));
+
+ const enum diagnostics_column_unit orig_unit = context->column_unit;
+ struct
+ {
+ const char *name;
+ enum diagnostics_column_unit unit;
+ } column_fields[] = {
+ {"display-column", DIAGNOSTICS_COLUMN_UNIT_DISPLAY},
+ {"byte-column", DIAGNOSTICS_COLUMN_UNIT_BYTE}
+ };
+ int the_column = INT_MIN;
+ for (int i = 0; i != sizeof column_fields / sizeof (*column_fields); ++i)
+ {
+ context->column_unit = column_fields[i].unit;
+ const int col = diagnostic_converted_column (context, exploc);
+ result->set (column_fields[i].name, new json::integer_number (col));
+ if (column_fields[i].unit == orig_unit)
+ the_column = col;
+ }
+ gcc_assert (the_column != INT_MIN);
+ result->set ("column", new json::integer_number (the_column));
+ context->column_unit = orig_unit;
return result;
}
/* Generate a JSON object for LOC_RANGE. */
static json::object *
-json_from_location_range (const location_range *loc_range, unsigned range_idx)
+json_from_location_range (diagnostic_context *context,
+ const location_range *loc_range, unsigned range_idx)
{
location_t caret_loc = get_pure_location (loc_range->m_loc);
location_t finish_loc = get_finish (loc_range->m_loc);
json::object *result = new json::object ();
- result->set ("caret", json_from_expanded_location (caret_loc));
+ result->set ("caret", json_from_expanded_location (context, caret_loc));
if (start_loc != caret_loc
&& start_loc != UNKNOWN_LOCATION)
- result->set ("start", json_from_expanded_location (start_loc));
+ result->set ("start", json_from_expanded_location (context, start_loc));
if (finish_loc != caret_loc
&& finish_loc != UNKNOWN_LOCATION)
- result->set ("finish", json_from_expanded_location (finish_loc));
+ result->set ("finish", json_from_expanded_location (context, finish_loc));
if (loc_range->m_label)
{
/* Generate a JSON object for HINT. */
static json::object *
-json_from_fixit_hint (const fixit_hint *hint)
+json_from_fixit_hint (diagnostic_context *context, const fixit_hint *hint)
{
json::object *fixit_obj = new json::object ();
location_t start_loc = hint->get_start_loc ();
- fixit_obj->set ("start", json_from_expanded_location (start_loc));
+ fixit_obj->set ("start", json_from_expanded_location (context, start_loc));
location_t next_loc = hint->get_next_loc ();
- fixit_obj->set ("next", json_from_expanded_location (next_loc));
+ fixit_obj->set ("next", json_from_expanded_location (context, next_loc));
fixit_obj->set ("string", new json::string (hint->get_string ()));
return fixit_obj;
else
{
/* Otherwise, make diag_obj be the top-level object within the group;
- add a "children" array. */
+ add a "children" array and record the column origin. */
toplevel_array->append (diag_obj);
cur_group = diag_obj;
cur_children_array = new json::array ();
diag_obj->set ("children", cur_children_array);
+ diag_obj->set ("column-origin",
+ new json::integer_number (context->column_origin));
}
const rich_location *richloc = diagnostic->richloc;
for (unsigned int i = 0; i < richloc->get_num_locations (); i++)
{
const location_range *loc_range = richloc->get_range (i);
- json::object *loc_obj = json_from_location_range (loc_range, i);
+ json::object *loc_obj = json_from_location_range (context, loc_range, i);
if (loc_obj)
loc_array->append (loc_obj);
}
for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
{
const fixit_hint *hint = richloc->get_fixit_hint (i);
- json::object *fixit_obj = json_from_fixit_hint (hint);
+ json::object *fixit_obj = json_from_fixit_hint (context, hint);
fixit_array->append (fixit_obj);
}
}
static void
test_unknown_location ()
{
- delete json_from_expanded_location (UNKNOWN_LOCATION);
+ test_diagnostic_context dc;
+ delete json_from_expanded_location (&dc, UNKNOWN_LOCATION);
}
/* Verify that we gracefully handle attempts to serialize bad
loc_range.m_range_display_kind = SHOW_RANGE_WITH_CARET;
loc_range.m_label = NULL;
- json::object *obj = json_from_location_range (&loc_range, 0);
+ test_diagnostic_context dc;
+ json::object *obj = json_from_location_range (&dc, &loc_range, 0);
/* We should have a "caret" value, but no "start" or "finish" values. */
ASSERT_TRUE (obj != NULL);
ASSERT_TRUE (obj->get ("caret") != NULL);