]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/diagnostic-format-json.cc
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / diagnostic-format-json.cc
index 7bda5c4ba8344360ff02f56874a5f45ff1e6a6a0..6da96f77fce240a2db98aac2bd4d0ed113c9c1b7 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "diagnostic.h"
+#include "selftest-diagnostic.h"
 #include "diagnostic-metadata.h"
 #include "json.h"
 #include "selftest.h"
@@ -43,21 +44,43 @@ static json::array *cur_children_array;
 /* 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);
 
@@ -68,13 +91,13 @@ json_from_location_range (const location_range *loc_range, unsigned range_idx)
   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)
     {
@@ -91,14 +114,14 @@ json_from_location_range (const location_range *loc_range, unsigned range_idx)
 /* 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;
@@ -190,11 +213,13 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
   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;
@@ -205,7 +230,7 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
   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);
     }
@@ -217,7 +242,7 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
       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);
        }
     }
@@ -320,7 +345,8 @@ namespace selftest {
 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
@@ -338,7 +364,8 @@ test_bad_endpoints ()
   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);