]> 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 53c3b630b1cda0e6ab5b130501beb6319b34a234..6da96f77fce240a2db98aac2bd4d0ed113c9c1b7 100644 (file)
@@ -1,5 +1,5 @@
 /* JSON output for diagnostics
-   Copyright (C) 2018-2019 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,8 @@ 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"
 
@@ -41,22 +43,44 @@ static json::array *cur_children_array;
 
 /* Generate a JSON object for LOC.  */
 
-static json::object *
-json_from_expanded_location (location_t loc)
+json::value *
+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::number (exploc.line));
-  result->set ("column", new json::number (exploc.column));
+  result->set ("line", new json::integer_number (exploc.line));
+
+  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);
 
@@ -67,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)
     {
@@ -90,19 +114,33 @@ 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;
 }
 
+/* Generate a JSON object for METADATA.  */
+
+static json::object *
+json_from_metadata (const diagnostic_metadata *metadata)
+{
+  json::object *metadata_obj = new json::object ();
+
+  if (metadata->get_cwe ())
+    metadata_obj->set ("cwe",
+                      new json::integer_number (metadata->get_cwe ()));
+
+  return metadata_obj;
+}
+
 /* No-op implementation of "begin_diagnostic" for JSON output.  */
 
 static void
@@ -154,6 +192,17 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
       free (option_text);
     }
 
+  if (context->get_option_url)
+    {
+      char *option_url = context->get_option_url (context,
+                                                 diagnostic->option_index);
+      if (option_url)
+       {
+         diag_obj->set ("option_url", new json::string (option_url));
+         free (option_url);
+       }
+    }
+
   /* If we've already emitted a diagnostic within this auto_diagnostic_group,
      then add diag_obj to its "children" array.  */
   if (cur_group)
@@ -164,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;
@@ -179,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);
     }
@@ -191,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);
        }
     }
@@ -200,6 +251,19 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
      TODO: functions
      TODO: inlining information
      TODO: macro expansion information.  */
+
+  if (diagnostic->metadata)
+    {
+      json::object *metadata_obj = json_from_metadata (diagnostic->metadata);
+      diag_obj->set ("metadata", metadata_obj);
+    }
+
+  const diagnostic_path *path = richloc->get_path ();
+  if (path && context->make_json_for_path)
+    {
+      json::value *path_value = context->make_json_for_path (context, path);
+      diag_obj->set ("path", path_value);
+    }
 }
 
 /* No-op implementation of "begin_group_cb" for JSON output.  */
@@ -256,6 +320,10 @@ diagnostic_output_format_init (diagnostic_context *context,
        context->begin_group_cb = json_begin_group;
        context->end_group_cb =  json_end_group;
        context->final_cb =  json_final_cb;
+       context->print_path = NULL; /* handled in json_end_diagnostic.  */
+
+       /* The metadata is handled in JSON format, rather than as text.  */
+       context->show_cwe = false;
 
        /* The option is handled in JSON format, rather than as text.  */
        context->show_option_requested = false;
@@ -277,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
@@ -295,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);