https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107941

--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by David Malcolm <dmalc...@gcc.gnu.org>:

https://gcc.gnu.org/g:4d1f71d49e396cb879d43dc96dc591079af66bbe

commit r15-2354-g4d1f71d49e396cb879d43dc96dc591079af66bbe
Author: David Malcolm <dmalc...@redhat.com>
Date:   Fri Jul 26 20:37:31 2024 -0400

    diagnostics: SARIF output: capture #include information (PR 107941; §3.34)

    This patch extends our SARIF output to capture relationships between
    locations within a result (§3.34).  In particular, this captures
    chains of #includes relating to diagnostics and to events within
    diagnostic paths.

    For example, consider:

    include-chain-1.c:

      #include "include-chain-1.h"

    include-chain-1.h:

      /* First set of decls, which will be referenced in notes.  */
      #include "include-chain-1-1.h"

      /* Second set of decls, which will trigger the errors.  */
      #include "include-chain-1-2.h"

    include-chain-1-1.h:

      int p;
      int q;

    include-chain-1-1.h:

      char p;
      char q;

    GCC's textual output emits:

      In file included from PATH/include-chain-1.h:5,
                       from PATH/include-chain-1.c:30:
      PATH/include-chain-1-2.h:1:6: error: conflicting types for 'p'; have
'char'
          1 | char p;
            |      ^
      In file included from PATH/include-chain-1.h:2:
      PATH/include-chain-1-1.h:1:5: note: previous declaration of 'p' with type
'int'
          1 | int p;
            |     ^
      PATH/include-chain-1-2.h:2:6: error: conflicting types for 'q'; have
'char'
          2 | char q;
            |      ^
      PATH/include-chain-1-1.h:2:5: note: previous declaration of 'q' with type
'int'
          2 | int q;
            |     ^

    With this patch, the SARIF output captures the include information for
    the two results, so that e.g. result[0]'s location[0] has:

      "relationships": [{"target": 0,
                         "kinds": ["isIncludedBy"]}],
      "id": 0

    and the "note" in relatedLocations[0] has:

      "message": {"text": "previous declaration of 'q' with type 'int'"},
      "relationships": [{"target": 2,
                        "kinds": ["isIncludedBy"]}],
      "id": 2},

    where these reference new locations within relatedLocations, such as this
for
    the "#include "include-chain-1-1.h" line in include-chain-1.h:

      {"physicalLocation": {"artifactLocation": {"uri": include-chain-1.h",
                                                 "uriBaseId": "PWD"},
                            "region": {"startLine": 5},
                            "contextRegion": {"startLine": 5,
                                              "snippet": {"text": "#include
\"include-chain-1-2.h\"\n"}}},
       "id": 1,
       "relationships": [{"target": 0,
                          "kinds": ["includes"]},
                         {"target": 4,
                          "kinds": ["isIncludedBy"]}]},

    effectively capturing the inclusion digraph in SARIF form:

     +-----------------------------------+ +----------------------------------+
     |"id": 0                            | |"id": 2                           |
     | error: "conflicting types for 'p';| | note: previous declaration of 'p'|
     |  have 'char'"|                    | | with type 'int'")                |
     | in include-chain-1-2.h            | | in include-chain-1-1.h           |
     +-----------------------------------+ +----------------------------------+
                       |                                      |
                       | included-by                          | included-by
                       V                                      V
      +--------------------------------+    +--------------------------------+
      |"id": 1                         |    |"id": 3                         |
      | #include "include-chain-1-2.h" |    | #include "include-chain-1-1.h" |
      | in include-chain-1.h           |    | in include-chain-1.h           |
      +--------------------------------+    +--------------------------------+
                             |                      |
                             | included-by          | included-by
                             V                      V
                      +------------------------------------+
                      |"id": 4                             |
                      | The  #include "include-chain-1.h"  |
                      | in include-chain-1.c               |
                      +------------------------------------+

    Locations only gain "id" fields if they need one, and the precise
    numbering of the IDs within a result is an implementation detail (the
    order in which references to the locations are made).

    To test all this non-trivial JSON from DejaGnu I needed to adapt the
    python testing code used by gcov, adding a new run-sarif-pytest based
    on run-gcov-pytest.

    gcc/ChangeLog:
            PR middle-end/107941
            * diagnostic-format-sarif.cc: Define INCLUDE_LIST and INCLUDE_MAP.
            (enum class location_relationship_kind): New.
            (diagnostic_artifact_role::scanned_file): New value.
            (class sarif_location_manager): New.
            (class sarif_result): Derive from sarif_location_manager rather
            than directly from sarif_object.
            (sarif_result::add_related_location): Convert to vfunc
            implementation.
            (sarif_location::m_relationships_map): New field.
            (class sarif_location_relationship): New.
            (class sarif_ice_notification): Derive from sarif_location_manager
            rather than directly from sarif_object.
            (sarif_builder::take_current_result): New.
            (sarif_builder::m_line_maps): New field.
            (sarif_builder::m_cur_group_result): Convert to std::unique_ptr.
            (sarif_artifact::add_role): Skip scanned_file.
            (get_artifact_role_string): Handle scanned_file.
            (sarif_location_manager::add_relationship_to_worklist): New.
            (sarif_location_manager::process_worklist): New.
            (sarif_location_manager::process_worklist_item): New.
            (sarif_result::on_nested_diagnostic): Pass *this to
            make_location_object.
            (sarif_location::lazily_add_id): New.
            (sarif_location::get_id): New.
            (get_string_for_location_relationship_kind): New.
            (sarif_location::lazily_add_relationship): New.
            (sarif_location::lazily_add_relationship_object): New.
            (sarif_location::lazily_add_relationships_array): New.
            (sarif_ice_notification::sarif_ice_notification): Fix overlong
line.
            Pass *this to make_locations_arr.
            (sarif_ice_notification::add_related_location): New.
            (sarif_location_relationship::sarif_location_relationship): New.
            (sarif_location_relationship::get_target_id): New.
            (sarif_location_relationship::lazily_add_kind): New.
            (sarif_builder::sarif_builder): Add "line_maps" param and use it
            to initialize m_line_maps.
            (sarif_builder::end_diagnostic): Update for m_cur_group_result
            becoming a std::unique_ptr.  Don't append to m_results_array yet.
            (sarif_builder::end_group): Append m_cur_group_result to
            m_results_array here, rather than in end_diagnostic.
            (sarif_builder::make_result_object): Pass result_obj to
            make_locations_arr and to make_code_flow_object.
            (sarif_builder::make_locations_arr): Add "loc_mgr" param and pass
            it to make_location_object.
            (sarif_builder::make_location_object): For two overloads, add
            "loc_mgr" param and call add_any_include_chain on the location.
            (sarif_builder::add_any_include_chain): New.
            (sarif_builder::make_location_object): New overload.
            (sarif_builder::make_code_flow_object): Add "result" param and
            pass it to make_thread_flow_location_object.
            (sarif_builder::make_thread_flow_location_object): Add "result"
            param and pass it to make_location_object.
            (sarif_builder::get_or_create_artifact): Handle scanned_file.
            (sarif_output_format::~sarif_output_format): Assert that there
            isn't a pending result.
            (sarif_output_format::sarif_output_format): Add "line_maps" param
            and pass it to m_builder's ctor.
            (sarif_stream_output_format::sarif_stream_output_format): Add
            "line_maps" param and pass it to base class ctor.
            (sarif_file_output_format::sarif_file_output_format): Likewise.
            (diagnostic_output_format_init_sarif_stderr): Pass "line_table"
            global to format.
            (diagnostic_output_format_init_sarif_file): Likewise.
            (diagnostic_output_format_init_sarif_stream): Likewise.
            (test_sarif_diagnostic_context::test_sarif_diagnostic_context):
            Likewise.
            (buffered_output_format::buffered_output_format): Likewise.
            (selftest::test_make_location_object): Likewise.
            (selftest::test_make_location_object): Create a sarif_result for
            use when calling make_location_object.
            * diagnostic.cc (diagnostic_context::finish): End any active
            diagnostic groups.
            (diagnostic_context::report_diagnostic): Assert that we're within
            a diagnostic group.
            * diagnostic.h (diagnostic_report_diagnostic): Add
            begin_group/end_group pair around call to
            diagnostic_context::report_diagnostic.
            * selftest-diagnostic.cc (test_diagnostic_context::report): Add
            begin_group/end_group pair around diagnostic_impl call.

    gcc/testsuite/ChangeLog:
            PR middle-end/107941
            * gcc.dg/sarif-output/include-chain-1-1.h: New test.
            * gcc.dg/sarif-output/include-chain-1-2.h: New test.
            * gcc.dg/sarif-output/include-chain-1.c: New test.
            * gcc.dg/sarif-output/include-chain-1.h: New test.
            * gcc.dg/sarif-output/include-chain-2.c: New test.
            * gcc.dg/sarif-output/include-chain-2.h: New test.
            * gcc.dg/sarif-output/sarif-output.exp: New file.
            * gcc.dg/sarif-output/sarif.py: New test, adapted from
            g++.dg/gcov/gcov.py.
            * gcc.dg/sarif-output/test-include-chain-1.py: New test.
            * gcc.dg/sarif-output/test-include-chain-2.py: New test.
            * lib/scansarif.exp (sarif-pytest-format-line): New, taken
            from lib/gcov.exp.
            (run-sarif-pytest): New, adapted from run-gcov-pytest in
            lib/gcov.exp.

    Signed-off-by: David Malcolm <dmalc...@redhat.com>

Reply via email to