Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Successful run of analyzer integration tests on x86_64-pc-linux-gnu. Pushed to trunk as r16-415-g9fb44cc4823106.
gcc/ChangeLog: * diagnostic-format-sarif.cc (maybe_get_sarif_kind): Add cases for new kinds of logical location. * doc/libgdiagnostics/topics/logical-locations.rst: Add new kinds of logical location for handling XML and JSON. * libgdiagnostics.cc (impl_logical_location_manager::get_kind): Add cases for new kinds of logical location. (diagnostic_text_sink::text_starter): Likewise, introducing a macro for this. (diagnostic_manager_debug_dump_logical_location): Likewise. * libgdiagnostics.h (enum diagnostic_logical_location_kind_t): Add new kinds of logical location for handling XML and JSON. * libsarifreplay.cc (handle_logical_location_object): Add entries to "kind_values" for decoding sarif logical location kinds relating to XML and JSON. * logical-location.h (enum logical_location_kind): Add new kinds of logical location for handling XML and JSON. gcc/testsuite/ChangeLog: * libgdiagnostics.dg/test-nested-logical-locations-json-c.py: New test. * libgdiagnostics.dg/test-nested-logical-locations-json.c: New test. * sarif-replay.dg/2.1.0-valid/3.33.7-json-example.sarif: New test. * sarif-replay.dg/2.1.0-valid/3.33.7-xml-example.sarif: New test. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/diagnostic-format-sarif.cc | 27 +++ .../topics/logical-locations.rst | 28 +++ gcc/libgdiagnostics.cc | 117 +++++++++++-- gcc/libgdiagnostics.h | 18 +- gcc/libsarifreplay.cc | 27 ++- gcc/logical-location.h | 18 +- .../test-nested-logical-locations-json-c.py | 79 +++++++++ .../test-nested-logical-locations-json.c | 165 ++++++++++++++++++ .../2.1.0-valid/3.33.7-json-example.sarif | 83 +++++++++ .../2.1.0-valid/3.33.7-xml-example.sarif | 77 ++++++++ 10 files changed, 626 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py create mode 100644 gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c create mode 100644 gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-json-example.sarif create mode 100644 gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-xml-example.sarif diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index 1b0743cb3c7d..454eaae4d905 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -2734,6 +2734,7 @@ maybe_get_sarif_kind (enum logical_location_kind kind) case LOGICAL_LOCATION_KIND_UNKNOWN: return nullptr; + /* Kinds within executable code. */ case LOGICAL_LOCATION_KIND_FUNCTION: return "function"; case LOGICAL_LOCATION_KIND_MEMBER: @@ -2750,6 +2751,32 @@ maybe_get_sarif_kind (enum logical_location_kind kind) return "parameter"; case LOGICAL_LOCATION_KIND_VARIABLE: return "variable"; + + /* Kinds within XML or HTML documents. */ + case LOGICAL_LOCATION_KIND_ELEMENT: + return "element"; + case LOGICAL_LOCATION_KIND_ATTRIBUTE: + return "attribute"; + case LOGICAL_LOCATION_KIND_TEXT: + return "text"; + case LOGICAL_LOCATION_KIND_COMMENT: + return "comment"; + case LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION: + return "processingInstruction"; + case LOGICAL_LOCATION_KIND_DTD: + return "dtd"; + case LOGICAL_LOCATION_KIND_DECLARATION: + return "declaration"; + + /* Kinds within JSON documents. */ + case LOGICAL_LOCATION_KIND_OBJECT: + return "object"; + case LOGICAL_LOCATION_KIND_ARRAY: + return "array"; + case LOGICAL_LOCATION_KIND_PROPERTY: + return "property"; + case LOGICAL_LOCATION_KIND_VALUE: + return "value"; } } diff --git a/gcc/doc/libgdiagnostics/topics/logical-locations.rst b/gcc/doc/libgdiagnostics/topics/logical-locations.rst index 85f239d6bb1e..184b56381910 100644 --- a/gcc/doc/libgdiagnostics/topics/logical-locations.rst +++ b/gcc/doc/libgdiagnostics/topics/logical-locations.rst @@ -51,6 +51,8 @@ source location This roughly corresponds to the ``kind`` property in SARIF v2.1.0 (`ยง3.33.7 <https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790976>`_). + Kinds within executable code: + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER @@ -67,6 +69,32 @@ source location .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE + Kinds within XML or HTML documents: + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION + + Kinds within JSON documents: + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY + + .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE + ``parent`` can be NULL; if non-NULL it can be used to express tree-like nesting of logical locations, such as in:: diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc index 39deb47248e1..70b0f36e0438 100644 --- a/gcc/libgdiagnostics.cc +++ b/gcc/libgdiagnostics.cc @@ -305,6 +305,7 @@ public: { default: gcc_unreachable (); + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: return LOGICAL_LOCATION_KIND_FUNCTION; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER: @@ -321,6 +322,30 @@ public: return LOGICAL_LOCATION_KIND_PARAMETER; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE: return LOGICAL_LOCATION_KIND_VARIABLE; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT: + return LOGICAL_LOCATION_KIND_ELEMENT; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE: + return LOGICAL_LOCATION_KIND_ATTRIBUTE; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT: + return LOGICAL_LOCATION_KIND_TEXT; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT: + return LOGICAL_LOCATION_KIND_COMMENT; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION: + return LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD: + return LOGICAL_LOCATION_KIND_DTD; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION: + return LOGICAL_LOCATION_KIND_DECLARATION; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT: + return LOGICAL_LOCATION_KIND_OBJECT; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY: + return LOGICAL_LOCATION_KIND_ARRAY; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY: + return LOGICAL_LOCATION_KIND_PROPERTY; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE: + return LOGICAL_LOCATION_KIND_VALUE; } } @@ -1097,21 +1122,57 @@ diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output, if (diag_logical_loc && diag_logical_loc != mgr.get_prev_diag_logical_loc ()) { pp_set_prefix (pp, nullptr); + + /* This macro is used to ensure that all format strings are visible to gettext + and checked at compile time. */ + +#define CASE(KIND, MSGID) \ + case KIND: \ + if (const char *name \ + = diag_logical_loc->m_fully_qualified_name.get_str ()) \ + { \ + pp_printf (pp, (MSGID), name); \ + pp_character (pp, ':'); \ + pp_newline (pp); \ + } \ + break; + switch (diag_logical_loc->m_kind) { default: break; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: - if (const char *name - = diag_logical_loc->m_fully_qualified_name.get_str ()) - { - pp_printf (pp, _("In function %qs"), name); - pp_character (pp, ':'); - pp_newline (pp); - } - break; - // TODO: handle other cases + + /* Kinds within executable code. */ + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, _("In function %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER, _("In member %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE, _("In module %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE, _("In namespace %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE, _("In type %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE, + _("In return type %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER, _("In parameter %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE, _("In variable %qs")) + + /* Kinds within XML or HTML documents. */ + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT, _("In element %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE, _("In attribute %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT, _("In text %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT, _("In comment %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION, + _("In processing instruction %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD, _("In DTD %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION, + _("In declaration %qs")) + + /* Kinds within JSON documents. */ + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT, _("In JSON object %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, _("In JSON array %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY, + _("In JSON property %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE, _("In JSON value %qs")) } + +#undef CASE } pp_set_prefix (pp, text_output.build_prefix (*info)); @@ -1515,6 +1576,7 @@ diagnostic_manager_debug_dump_logical_location (const diagnostic_manager *diag_m { default: gcc_unreachable (); + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: fprintf (out, "function"); break; @@ -1539,6 +1601,41 @@ diagnostic_manager_debug_dump_logical_location (const diagnostic_manager *diag_m case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE: fprintf (out, "variable"); break; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT: + fprintf (out, "element"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE: + fprintf (out, "attribute"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT: + fprintf (out, "text"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT: + fprintf (out, "comment"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION: + fprintf (out, "processing_instruction"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD: + fprintf (out, "dtd"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION: + fprintf (out, "declaration"); + break; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT: + fprintf (out, "object"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY: + fprintf (out, "array"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY: + fprintf (out, "property"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE: + fprintf (out, "value"); + break; } if (auto parent = loc->m_parent) { diff --git a/gcc/libgdiagnostics.h b/gcc/libgdiagnostics.h index 14567a523eb7..f957779604bd 100644 --- a/gcc/libgdiagnostics.h +++ b/gcc/libgdiagnostics.h @@ -161,6 +161,7 @@ typedef struct diagnostic_logical_location diagnostic_logical_location; enum diagnostic_logical_location_kind_t { + /* Kinds within executable code. */ DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER, DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE, @@ -168,7 +169,22 @@ enum diagnostic_logical_location_kind_t DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE, DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE, DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER, - DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE + DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE, + + /* Kinds within XML or HTML documents. */ + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION, + + /* Kinds within JSON documents. */ + DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE }; /* A "diagnostic" is an opaque bundle of state for a particular diff --git a/gcc/libsarifreplay.cc b/gcc/libsarifreplay.cc index f5f1f2041b43..7c7be8d98642 100644 --- a/gcc/libsarifreplay.cc +++ b/gcc/libsarifreplay.cc @@ -2008,7 +2008,32 @@ handle_logical_location_object (const json::object &logical_loc_obj, { "parameter", DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER }, { "variable", - DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE } }; + DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE }, + + { "element", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT }, + { "attribute", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE }, + { "text", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT }, + { "comment", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT }, + { "processingInstruction", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION }, + { "dtd", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD }, + { "declaration", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION }, + + { "object", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT }, + { "array", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY }, + { "property", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY }, + { "value", + DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE }, + }; auto result = get_value_from_json_string<enum diagnostic_logical_location_kind_t> (*kind_str, kind_prop, kind_values, ARRAY_SIZE (kind_values)); diff --git a/gcc/logical-location.h b/gcc/logical-location.h index 4374b096fb05..dba9dc4010bf 100644 --- a/gcc/logical-location.h +++ b/gcc/logical-location.h @@ -33,6 +33,7 @@ enum logical_location_kind { LOGICAL_LOCATION_KIND_UNKNOWN, + /* Kinds within executable code. */ LOGICAL_LOCATION_KIND_FUNCTION, LOGICAL_LOCATION_KIND_MEMBER, LOGICAL_LOCATION_KIND_MODULE, @@ -40,7 +41,22 @@ enum logical_location_kind LOGICAL_LOCATION_KIND_TYPE, LOGICAL_LOCATION_KIND_RETURN_TYPE, LOGICAL_LOCATION_KIND_PARAMETER, - LOGICAL_LOCATION_KIND_VARIABLE + LOGICAL_LOCATION_KIND_VARIABLE, + + /* Kinds within XML or HTML documents. */ + LOGICAL_LOCATION_KIND_ELEMENT, + LOGICAL_LOCATION_KIND_ATTRIBUTE, + LOGICAL_LOCATION_KIND_TEXT, + LOGICAL_LOCATION_KIND_COMMENT, + LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION, + LOGICAL_LOCATION_KIND_DTD, + LOGICAL_LOCATION_KIND_DECLARATION, + + /* Kinds within JSON documents. */ + LOGICAL_LOCATION_KIND_OBJECT, + LOGICAL_LOCATION_KIND_ARRAY, + LOGICAL_LOCATION_KIND_PROPERTY, + LOGICAL_LOCATION_KIND_VALUE }; /* We want to efficiently support passing around logical locations in the diff --git a/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py new file mode 100644 index 000000000000..39cc1a9cb0b9 --- /dev/null +++ b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py @@ -0,0 +1,79 @@ +from sarif import * + +import pytest + +@pytest.fixture(scope='function', autouse=True) +def sarif(): + return sarif_from_env() + +def test_sarif_output_with_logical_location(sarif): + schema = sarif['$schema'] + assert schema == 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json' + + version = sarif['version'] + assert version == '2.1.0' + + runs = sarif['runs'] + run = runs[0] + + tool = run['tool'] + assert tool['driver']['name'] == 'test-nested-logical-locations-json.c.exe' + + results = run['results'] + assert len(results) == 2 + + result = results[0] + assert result['ruleId'] == 'warning' + assert result['level'] == 'warning' + assert result['message']['text'] == "product ID is blank" + assert len(result['locations']) == 1 + location = result['locations'][0] + assert len(location['logicalLocations']) == 1 + logical_loc = location['logicalLocations'][0] + assert logical_loc['index'] == 3 + assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds/1' + + result = results[1] + assert result['ruleId'] == 'warning' + assert result['level'] == 'warning' + assert result['message']['text'] == "value is negative" + assert len(result['locations']) == 1 + location = result['locations'][0] + assert len(location['logicalLocations']) == 1 + logical_loc = location['logicalLocations'][0] + assert logical_loc['index'] == 4 + assert logical_loc['fullyQualifiedName'] == '/orders/0/total' + + # Check theRun.logicalLocations + assert 'logicalLocations' in run + assert len(run['logicalLocations']) == 5 + logical_loc = run['logicalLocations'][0] + assert logical_loc['name'] == 'orders' + assert logical_loc['fullyQualifiedName'] == '/orders' + assert logical_loc['kind'] == 'array' + assert logical_loc['index'] == 0 + logical_loc = run['logicalLocations'][1] + assert logical_loc['name'] == '0' + assert logical_loc['fullyQualifiedName'] == '/orders/0' + assert logical_loc['kind'] == 'object' + assert logical_loc['parentIndex'] == 0 + assert logical_loc['index'] == 1 + logical_loc = run['logicalLocations'][2] + assert logical_loc['name'] == 'productIds' + assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds' + assert logical_loc['kind'] == 'array' + assert logical_loc['parentIndex'] == 1 + assert logical_loc['index'] == 2 + logical_loc = run['logicalLocations'][3] + assert logical_loc['name'] == '1' + assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds/1' + assert logical_loc['kind'] == 'value' + assert logical_loc['parentIndex'] == 2 + assert logical_loc['index'] == 3 + logical_loc = run['logicalLocations'][4] + assert logical_loc['name'] == 'total' + assert logical_loc['fullyQualifiedName'] == '/orders/0/total' + assert logical_loc['kind'] == 'property' + assert logical_loc['parentIndex'] == 1 + assert logical_loc['index'] == 4 + diff --git a/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c new file mode 100644 index 000000000000..d06450e1349c --- /dev/null +++ b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c @@ -0,0 +1,165 @@ +/* Example of nested logical locations, based on the JSON example in + SARIF v2.1.0, 3.33.7 "kind" property; + though see https://github.com/oasis-tcs/sarif-spec/issues/670 + + Intended output is similar to: + +In JSON value '/orders/0/productIds/1': +PATH/test-nested-logical-locations-json.c:28:32: warning: product ID is blank + 28 | "productIds": [ "A-101", "", "A-223" ], + | ^~ +In JSON property '/orders/0/total': +PATH/test-nested-logical-locations-json.c:29:16: warning: value is negative + 29 | "total": "-3.25" + | ^~~~~~~ + + along with the equivalent in SARIF, capturing JSON structure + as nested logical locations. */ + +#include "libgdiagnostics.h" +#include "test-helpers.h" + +/* Placeholder source: +_________1111111111222222222233333333334444444444 +1234567890123456789012345678901234567890123456789 +{ + "orders": [ + { + "productIds": [ "A-101", "", "A-223" ], + "total": "-3.25" + } + ] +} +*/ +const int start_line_num = __LINE__ - 9; +const int line_num_of_product_ids = start_line_num + 3; +const int line_num_of_total = line_num_of_product_ids + 1; + +#include <assert.h> + +int +main () +{ + begin_test ("test-nested-logical-locations-json.c.exe", + "test-nested-logical-locations-json.c.sarif", + __FILE__, "c"); + + /* Create tree of logical locations. */ + /* begin quoted source */ + const diagnostic_logical_location *logical_loc_orders_arr + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, + NULL, /* parent */ + "orders", + "/orders", + NULL); + const diagnostic_logical_location *logical_loc_order_0 + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT, + logical_loc_orders_arr, /* parent */ + "0", + "/orders/0", + NULL); + const diagnostic_logical_location *logical_loc_product_ids + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, + logical_loc_order_0, /* parent */ + "productIds", + "/orders/0/productIds", + NULL); + const diagnostic_logical_location *logical_loc_element_1 + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE, + logical_loc_product_ids, /* parent */ + "1", + "/orders/0/productIds/1", + NULL); + const diagnostic_logical_location *logical_loc_total + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY, + logical_loc_order_0, /* parent */ + "total", + "/orders/0/total", + NULL); + /* end quoted source */ + + { + const int line_num = line_num_of_product_ids; + const diagnostic_physical_location *loc_start + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 32); + const diagnostic_physical_location *loc_end + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 33); + const diagnostic_physical_location *loc_range + = diagnostic_manager_new_location_from_range (diag_mgr, + loc_start, + loc_start, + loc_end); + + diagnostic *d = diagnostic_begin (diag_mgr, + DIAGNOSTIC_LEVEL_WARNING); + diagnostic_set_location (d, loc_range); + + diagnostic_set_logical_location (d, logical_loc_element_1); + + diagnostic_finish (d, "product ID is blank"); + } + { + const int line_num = line_num_of_total; + const diagnostic_physical_location *loc_start + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 16); + const diagnostic_physical_location *loc_end + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 22); + const diagnostic_physical_location *loc_range + = diagnostic_manager_new_location_from_range (diag_mgr, + loc_start, + loc_start, + loc_end); + + diagnostic *d = diagnostic_begin (diag_mgr, + DIAGNOSTIC_LEVEL_WARNING); + diagnostic_set_location (d, loc_range); + + diagnostic_set_logical_location (d, logical_loc_total); + + diagnostic_finish (d, "value is negative"); + } + + return end_test (); +} + +/* Check the output from the text sink. */ +/* { dg-begin-multiline-output "" } +In JSON value '/orders/0/productIds/1': + { dg-end-multiline-output "" } */ +/* { dg-regexp "\[^\n\r\]+test-nested-logical-locations-json.c:28:32: warning: product ID is blank" } */ +/* { dg-begin-multiline-output "" } + 28 | "productIds": [ "A-101", "", "A-223" ], + | ^~ + { dg-end-multiline-output "" } */ +/* { dg-begin-multiline-output "" } +In JSON property '/orders/0/total': + { dg-end-multiline-output "" } */ +/* { dg-regexp "\[^\n\r\]+test-nested-logical-locations-json.c:29:16: warning: value is negative" } */ +/* { dg-begin-multiline-output "" } + 29 | "total": "-3.25" + | ^~~~~~~ + { dg-end-multiline-output "" } */ + +/* Verify that some JSON was written to a file with the expected name: + { dg-final { verify-sarif-file } } */ + +/* Use a Python script to verify various properties about the generated + .sarif file: + { dg-final { run-sarif-pytest test-nested-logical-locations-json.c "test-nested-logical-locations-json-c.py" } } */ diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-json-example.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-json-example.sarif new file mode 100644 index 000000000000..6e4cf5b38330 --- /dev/null +++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-json-example.sarif @@ -0,0 +1,83 @@ +/* Adapted from the JSON example in SARIF v2.1.0, 3.33.7 "kind" property; + see https://github.com/oasis-tcs/sarif-spec/issues/670 */ +{ + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "example JSON scanner" + } + }, + "results": [ + { + "message": {"text": "product ID is blank"}, + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "/orders/0/productIds/1", + "index": 3 + } + ] + } + ] + }, + { + "message": {"text": "value is negative"}, + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "/orders/0/total", + "index": 4 + } + ] + } + ] + } + ], + "logicalLocations": [ + { + "name": "orders", + "fullyQualifiedName": "/orders", + "kind": "array" + }, + { + "name": "0", + "fullyQualifiedName": "/orders/0", + "kind": "object", + "parentIndex": 0 + }, + { + "name": "productIds", + "fullyQualifiedName": "/orders/0/productIds", + "kind": "array", + "parentIndex": 1 + }, + { + "name": "1", + "fullyQualifiedName": "/orders/0/productIds/1", + "kind": "value", + "parentIndex": 2 + }, + { + "name": "total", + "fullyQualifiedName": "/orders/0/total", + "kind": "property", + "parentIndex": 1 + } + ] + } + ] +} + +/* { dg-begin-multiline-output "" } +In JSON value '/orders/0/productIds/1': +example JSON scanner: warning: product ID is blank + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } +In JSON property '/orders/0/total': +example JSON scanner: warning: value is negative + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-xml-example.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-xml-example.sarif new file mode 100644 index 000000000000..36afc6592916 --- /dev/null +++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.33.7-xml-example.sarif @@ -0,0 +1,77 @@ +/* Adapted from the XML example in SARIF v2.1.0, 3.33.7 "kind" property; + see also https://github.com/oasis-tcs/sarif-spec/issues/669 */ +{ + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "example XML scanner" + } + }, + "results": [ + { + "message": {"text": "empty value"}, + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "/orders/order[1]/@number", + "index": 2 + } + ] + } + ] + }, + { + "message": {"text": "total is negative"}, + "locations": [ + { + "logicalLocations": [ + { + "fullyQualifiedName": "/orders/order[1]/total/text()", + "index": 3 + } + ] + } + ] + } + ], + "logicalLocations": [ + { + "name": "orders", + "fullyQualifiedName": "/orders", + "kind": "element" + }, + { + "name": "order[1]", + "fullyQualifiedName": "/orders/order[1]", + "kind": "element", + "parentIndex": 0 + }, + { + "name": "number", + "fullyQualifiedName": "/orders/order[1]/@number", + "kind": "attribute", + "parentIndex": 1 + }, + { + "name": "text", + "fullyQualifiedName": "/orders/order[1]/total/text()", + "kind": "text", + "parentIndex": 1 + } + ] + } + ] +} + +/* { dg-begin-multiline-output "" } +In attribute '/orders/order[1]/@number': +example XML scanner: warning: empty value + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } +In text '/orders/order[1]/total/text()': +example XML scanner: warning: total is negative + { dg-end-multiline-output "" } */ -- 2.26.3