diagnostics: add SARIF output format
This patch adds support to gcc's diagnostic subsystem for emitting diagnostics in SARIF, aka the Static Analysis Results Interchange Format: https://sarifweb.azurewebsites.net/ by extending -fdiagnostics-format= to add two new options: -fdiagnostics-format=sarif-stderr and: -fdiagnostics-format=sarif-file The patch targets SARIF v2.1.0 This is a JSON-based format suited for capturing the results of static analysis tools (like GCC's -fanalyzer), but it can also be used for plain GCC warnings and errors. SARIF supports per-event metadata in diagnostic paths such as ["acquire", "resource"] and ["release", "lock"] (specifically, the threadFlowLocation "kinds" property: SARIF v2.1.0 section 3.38.8), so the patch extends GCC"s diagnostic_event subclass with a "struct meaning" with similar purpose. The patch implements this for -fanalyzer so that the various state-machine-based warnings set these in the SARIF output. The heart of the implementation is in the new file diagnostic-format-sarif.cc. Much of the rest of the patch is interface classes, isolating the diagnostic subsystem (which has no knowledge of e.g. tree or langhook) from the "client" code in the compiler proper cc1 etc). The patch adds a langhook for specifying the SARIF v2.1.0 "artifact.sourceLanguage" property, based on the list in SARIF v2.1.0 Appendix J. The patch adds automated DejaGnu tests to our testsuite via new scan-sarif-file and scan-sarif-file-not directives (although these merely use regexps, rather than attempting to use a proper JSON parser). I've tested the patch by hand using the validator at: https://sarifweb.azurewebsites.net/Validation and the react-based viewer at: https://microsoft.github.io/sarif-web-component/ which successfully shows most of the information (although not paths, and not CWE IDs), and I've fixed all validation errors I've seen (though bugs no doubt remain). I've also tested the generated SARIF using the VS Code extension linked to from the SARIF website; I'm a novice with VS Code, but it seems to be able to handle my generated SARIF files (e.g. showing the data in the SARIF tab, and showing squiggly underlines under issues, and when I click on them, it visualizes the events in the path inline within the source window). Has anyone written an Emacs mode for SARIF files? (pretty please) gcc/ChangeLog: * Makefile.in (OBJS): Add tree-diagnostic-client-data-hooks.o and tree-logical-location.o. (OBJS-libcommon): Add diagnostic-format-sarif.o; reorder. (CFLAGS-tree-diagnostic-client-data-hooks.o): Add TARGET_NAME. * common.opt (fdiagnostics-format=): Add sarif-stderr and sarif-file. (sarif-stderr, sarif-file): New enum values. * diagnostic-client-data-hooks.h: New file. * diagnostic-format-sarif.cc: New file. * diagnostic-path.h (enum diagnostic_event::verb): New enum. (enum diagnostic_event::noun): New enum. (enum diagnostic_event::property): New enum. (struct diagnostic_event::meaning): New struct. (diagnostic_event::get_logical_location): New vfunc. (diagnostic_event::get_meaning): New vfunc. (simple_diagnostic_event::get_logical_location): New vfunc impl. (simple_diagnostic_event::get_meaning): New vfunc impl. * diagnostic.cc: Include "diagnostic-client-data-hooks.h". (diagnostic_initialize): Initialize m_client_data_hooks. (diagnostic_finish): Clean up m_client_data_hooks. (diagnostic_event::meaning::dump_to_pp): New. (diagnostic_event::meaning::maybe_get_verb_str): New. (diagnostic_event::meaning::maybe_get_noun_str): New. (diagnostic_event::meaning::maybe_get_property_str): New. (get_cwe_url): Make non-static. (diagnostic_output_format_init): Handle DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR and DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE. * diagnostic.h (enum diagnostics_output_format): Add DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR and DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE. (class diagnostic_client_data_hooks): New forward decl. (class logical_location): New forward decl. (diagnostic_context::m_client_data_hooks): New field. (diagnostic_output_format_init_sarif_stderr): New decl. (diagnostic_output_format_init_sarif_file): New decl. (get_cwe_url): New decl. * doc/invoke.texi (-fdiagnostics-format=): Add sarif-stderr and sarif-file. * doc/sourcebuild.texi (Scan a particular file): Add scan-sarif-file and scan-sarif-file-not. * langhooks-def.h (lhd_get_sarif_source_language): New decl. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): New macro. (LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE. * langhooks.cc (lhd_get_sarif_source_language): New. * langhooks.h (lang_hooks::get_sarif_source_language): New field. * logical-location.h: New file. * plugin.cc (struct for_each_plugin_closure): New. (for_each_plugin_cb): New. (for_each_plugin): New. * plugin.h (for_each_plugin): New decl. * tree-diagnostic-client-data-hooks.cc: New file. * tree-diagnostic.cc: Include "diagnostic-client-data-hooks.h". (tree_diagnostics_defaults): Populate m_client_data_hooks. * tree-logical-location.cc: New file. * tree-logical-location.h: New file. gcc/ada/ChangeLog: * gcc-interface/misc.cc (gnat_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/analyzer/ChangeLog: * checker-path.cc (checker_event::get_meaning): New. (function_entry_event::get_meaning): New. (state_change_event::get_desc): Add dump of meaning of the event to the -fanalyzer-verbose-state-changes output. (state_change_event::get_meaning): New. (cfg_edge_event::get_meaning): New. (call_event::get_meaning): New. (return_event::get_meaning): New. (start_consolidated_cfg_edges_event::get_meaning): New. (warning_event::get_meaning): New. * checker-path.h: Include "tree-logical-location.h". (checker_event::checker_event): Construct m_logical_loc. (checker_event::get_logical_location): New. (checker_event::get_meaning): New decl. (checker_event::m_logical_loc): New. (function_entry_event::get_meaning): New decl. (state_change_event::get_meaning): New decl. (cfg_edge_event::get_meaning): New decl. (call_event::get_meaning): New decl. (return_event::get_meaning): New decl. (start_consolidated_cfg_edges_event::get_meaning): New. (warning_event::get_meaning): New decl. * pending-diagnostic.h: Include "diagnostic-path.h". (pending_diagnostic::get_meaning_for_state_change): New vfunc. * sm-file.cc (file_diagnostic::get_meaning_for_state_change): New vfunc impl. * sm-malloc.cc (malloc_diagnostic::get_meaning_for_state_change): Likewise. * sm-sensitive.cc (exposure_through_output_file::get_meaning_for_state_change): Likewise. * sm-taint.cc (taint_diagnostic::get_meaning_for_state_change): Likewise. * varargs.cc (va_list_sm_diagnostic::get_meaning_for_state_change): Likewise. gcc/c/ChangeLog: * c-lang.cc (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. (c_get_sarif_source_language): New. * c-tree.h (c_get_sarif_source_language): New decl. gcc/cp/ChangeLog: * cp-lang.cc (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. (cp_get_sarif_source_language): New. gcc/d/ChangeLog: * d-lang.cc (d_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/fortran/ChangeLog: * f95-lang.cc (gfc_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/go/ChangeLog: * go-lang.cc (go_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/objc/ChangeLog: * objc-act.h (objc_get_sarif_source_language): New decl. * objc-lang.cc (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. (objc_get_sarif_source_language): New. gcc/testsuite/ChangeLog: * c-c++-common/diagnostic-format-sarif-file-1.c: New test. * c-c++-common/diagnostic-format-sarif-file-2.c: New test. * c-c++-common/diagnostic-format-sarif-file-3.c: New test. * c-c++-common/diagnostic-format-sarif-file-4.c: New test. * gcc.dg/analyzer/file-meaning-1.c: New test. * gcc.dg/analyzer/malloc-meaning-1.c: New test. * gcc.dg/analyzer/malloc-sarif-1.c: New test. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::get_meaning_for_state_change): New vfunc impl. * gcc.dg/plugin/diagnostic-test-paths-5.c: New test. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add diagnostic-test-paths-5.c to tests for diagnostic_plugin_test_paths.c. * lib/gcc-dg.exp: Load scansarif.exp. * lib/scansarif.exp: New test. libatomic/ChangeLog: * testsuite/lib/libatomic.exp: Add load_gcc_lib of scansarif.exp. libgomp/ChangeLog: * testsuite/lib/libgomp.exp: Add load_gcc_lib of scansarif.exp. libitm/ChangeLog: * testsuite/lib/libitm.exp: Add load_gcc_lib of scansarif.exp. libphobos/ChangeLog: * testsuite/lib/libphobos-dg.exp: Add load_gcc_lib of scansarif.exp. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
5ab73173cc
commit
6cf276ddf2
52 changed files with 3005 additions and 13 deletions
|
@ -1617,6 +1617,7 @@ OBJS = \
|
|||
tree-data-ref.o \
|
||||
tree-dfa.o \
|
||||
tree-diagnostic.o \
|
||||
tree-diagnostic-client-data-hooks.o \
|
||||
tree-diagnostic-path.o \
|
||||
tree-dump.o \
|
||||
tree-eh.o \
|
||||
|
@ -1625,6 +1626,7 @@ OBJS = \
|
|||
tree-inline.o \
|
||||
tree-into-ssa.o \
|
||||
tree-iterator.o \
|
||||
tree-logical-location.o \
|
||||
tree-loop-distribution.o \
|
||||
tree-nested.o \
|
||||
tree-nrv.o \
|
||||
|
@ -1728,9 +1730,12 @@ OBJS = \
|
|||
# Objects in libcommon.a, potentially used by all host binaries and with
|
||||
# no target dependencies.
|
||||
OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
|
||||
diagnostic-show-locus.o diagnostic-format-json.o json.o \
|
||||
diagnostic-format-json.o \
|
||||
diagnostic-format-sarif.o \
|
||||
diagnostic-show-locus.o \
|
||||
edit-context.o \
|
||||
pretty-print.o intl.o \
|
||||
json.o \
|
||||
sbitmap.o \
|
||||
vec.o input.o hash-table.o ggc-none.o memory-block.o \
|
||||
selftest.o selftest-diagnostic.o sort.o
|
||||
|
@ -2368,6 +2373,7 @@ s-bversion: BASE-VER
|
|||
$(STAMP) s-bversion
|
||||
|
||||
CFLAGS-toplev.o += -DTARGET_NAME=\"$(target_noncanonical)\"
|
||||
CFLAGS-tree-diagnostic-client-data-hooks.o += -DTARGET_NAME=\"$(target_noncanonical)\"
|
||||
CFLAGS-optinfo-emit-json.o += -DTARGET_NAME=\"$(target_noncanonical)\" $(ZLIBINC)
|
||||
CFLAGS-analyzer/engine.o += $(ZLIBINC)
|
||||
|
||||
|
|
|
@ -1292,6 +1292,15 @@ gnat_eh_personality (void)
|
|||
return gnat_eh_personality_decl;
|
||||
}
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
|
||||
based on the list in SARIF v2.1.0 Appendix J. */
|
||||
|
||||
static const char *
|
||||
gnat_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "ada";
|
||||
}
|
||||
|
||||
/* Initialize language-specific bits of tree_contains_struct. */
|
||||
|
||||
static void
|
||||
|
@ -1414,6 +1423,8 @@ get_lang_specific (tree node)
|
|||
#define LANG_HOOKS_DEEP_UNSHARING true
|
||||
#undef LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS
|
||||
#define LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS true
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE gnat_get_sarif_source_language
|
||||
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
|
|
|
@ -112,6 +112,15 @@ event_kind_to_string (enum event_kind ek)
|
|||
|
||||
/* class checker_event : public diagnostic_event. */
|
||||
|
||||
/* No-op implementation of diagnostic_event::get_meaning vfunc for
|
||||
checker_event: checker events have no meaning by default. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
checker_event::get_meaning () const
|
||||
{
|
||||
return meaning ();
|
||||
}
|
||||
|
||||
/* Dump this event to PP (for debugging/logging purposes). */
|
||||
|
||||
void
|
||||
|
@ -242,6 +251,15 @@ function_entry_event::get_desc (bool can_colorize) const
|
|||
return make_label_text (can_colorize, "entry to %qE", m_fndecl);
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
function entry. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
function_entry_event::get_meaning () const
|
||||
{
|
||||
return meaning (VERB_enter, NOUN_function);
|
||||
}
|
||||
|
||||
/* class state_change_event : public checker_event. */
|
||||
|
||||
/* state_change_event's ctor. */
|
||||
|
@ -292,25 +310,33 @@ state_change_event::get_desc (bool can_colorize) const
|
|||
{
|
||||
if (flag_analyzer_verbose_state_changes)
|
||||
{
|
||||
/* Get any "meaning" of event. */
|
||||
diagnostic_event::meaning meaning = get_meaning ();
|
||||
pretty_printer meaning_pp;
|
||||
meaning.dump_to_pp (&meaning_pp);
|
||||
|
||||
/* Append debug version. */
|
||||
label_text result;
|
||||
if (m_origin)
|
||||
result = make_label_text
|
||||
(can_colorize,
|
||||
"%s (state of %qE: %qs -> %qs, origin: %qE)",
|
||||
"%s (state of %qE: %qs -> %qs, origin: %qE, meaning: %s)",
|
||||
custom_desc.m_buffer,
|
||||
var,
|
||||
m_from->get_name (),
|
||||
m_to->get_name (),
|
||||
origin);
|
||||
origin,
|
||||
pp_formatted_text (&meaning_pp));
|
||||
else
|
||||
result = make_label_text
|
||||
(can_colorize,
|
||||
"%s (state of %qE: %qs -> %qs, NULL origin)",
|
||||
"%s (state of %qE: %qs -> %qs, NULL origin, meaning: %s)",
|
||||
custom_desc.m_buffer,
|
||||
var,
|
||||
m_from->get_name (),
|
||||
m_to->get_name ());
|
||||
m_to->get_name (),
|
||||
pp_formatted_text (&meaning_pp));
|
||||
|
||||
custom_desc.maybe_free ();
|
||||
return result;
|
||||
}
|
||||
|
@ -357,6 +383,26 @@ state_change_event::get_desc (bool can_colorize) const
|
|||
}
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
state change events: delegate to the pending_diagnostic to
|
||||
get any meaning. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
state_change_event::get_meaning () const
|
||||
{
|
||||
if (m_pending_diagnostic)
|
||||
{
|
||||
region_model *model = m_dst_state.m_region_model;
|
||||
tree var = model->get_representative_tree (m_sval);
|
||||
tree origin = model->get_representative_tree (m_origin);
|
||||
return m_pending_diagnostic->get_meaning_for_state_change
|
||||
(evdesc::state_change (false, var, origin,
|
||||
m_from, m_to, m_emission_id, *this));
|
||||
}
|
||||
else
|
||||
return meaning ();
|
||||
}
|
||||
|
||||
/* class superedge_event : public checker_event. */
|
||||
|
||||
/* Get the callgraph_superedge for this superedge_event, which must be
|
||||
|
@ -432,6 +478,21 @@ cfg_edge_event::cfg_edge_event (enum event_kind kind,
|
|||
gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE);
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
CFG edge events. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
cfg_edge_event::get_meaning () const
|
||||
{
|
||||
const cfg_superedge& cfg_sedge = get_cfg_superedge ();
|
||||
if (cfg_sedge.true_value_p ())
|
||||
return meaning (VERB_branch, PROPERTY_true);
|
||||
else if (cfg_sedge.false_value_p ())
|
||||
return meaning (VERB_branch, PROPERTY_false);
|
||||
else
|
||||
return meaning ();
|
||||
}
|
||||
|
||||
/* class start_cfg_edge_event : public cfg_edge_event. */
|
||||
|
||||
/* Implementation of diagnostic_event::get_desc vfunc for
|
||||
|
@ -690,6 +751,15 @@ call_event::get_desc (bool can_colorize) const
|
|||
get_caller_fndecl ());
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
function call events. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
call_event::get_meaning () const
|
||||
{
|
||||
return meaning (VERB_call, NOUN_function);
|
||||
}
|
||||
|
||||
/* Override of checker_event::is_call_p for calls. */
|
||||
|
||||
bool
|
||||
|
@ -760,6 +830,15 @@ return_event::get_desc (bool can_colorize) const
|
|||
m_src_snode->m_fun->decl);
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
function return events. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
return_event::get_meaning () const
|
||||
{
|
||||
return meaning (VERB_return, NOUN_function);
|
||||
}
|
||||
|
||||
/* Override of checker_event::is_return_p for returns. */
|
||||
|
||||
bool
|
||||
|
@ -778,6 +857,16 @@ start_consolidated_cfg_edges_event::get_desc (bool can_colorize) const
|
|||
m_edge_sense ? "true" : "false");
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
start_consolidated_cfg_edges_event. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
start_consolidated_cfg_edges_event::get_meaning () const
|
||||
{
|
||||
return meaning (VERB_branch,
|
||||
(m_edge_sense ? PROPERTY_true : PROPERTY_false));
|
||||
}
|
||||
|
||||
/* class setjmp_event : public checker_event. */
|
||||
|
||||
/* Implementation of diagnostic_event::get_desc vfunc for
|
||||
|
@ -977,6 +1066,15 @@ warning_event::get_desc (bool can_colorize) const
|
|||
return label_text::borrow ("here");
|
||||
}
|
||||
|
||||
/* Implementation of diagnostic_event::get_meaning vfunc for
|
||||
warning_event. */
|
||||
|
||||
diagnostic_event::meaning
|
||||
warning_event::get_meaning () const
|
||||
{
|
||||
return meaning (VERB_danger, NOUN_unknown);
|
||||
}
|
||||
|
||||
/* Print a single-line representation of this path to PP. */
|
||||
|
||||
void
|
||||
|
|
|
@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef GCC_ANALYZER_CHECKER_PATH_H
|
||||
#define GCC_ANALYZER_CHECKER_PATH_H
|
||||
|
||||
#include "tree-logical-location.h"
|
||||
|
||||
namespace ana {
|
||||
|
||||
/* An enum for discriminating between the concrete subclasses of
|
||||
|
@ -85,7 +87,8 @@ public:
|
|||
checker_event (enum event_kind kind,
|
||||
location_t loc, tree fndecl, int depth)
|
||||
: m_kind (kind), m_loc (loc), m_fndecl (fndecl), m_depth (depth),
|
||||
m_pending_diagnostic (NULL), m_emission_id ()
|
||||
m_pending_diagnostic (NULL), m_emission_id (),
|
||||
m_logical_loc (fndecl)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -94,6 +97,14 @@ public:
|
|||
location_t get_location () const final override { return m_loc; }
|
||||
tree get_fndecl () const final override { return m_fndecl; }
|
||||
int get_stack_depth () const final override { return m_depth; }
|
||||
const logical_location *get_logical_location () const final override
|
||||
{
|
||||
if (m_fndecl)
|
||||
return &m_logical_loc;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
meaning get_meaning () const override;
|
||||
|
||||
/* Additional functionality. */
|
||||
|
||||
|
@ -122,6 +133,7 @@ public:
|
|||
int m_depth;
|
||||
pending_diagnostic *m_pending_diagnostic;
|
||||
diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
|
||||
tree_logical_location m_logical_loc;
|
||||
};
|
||||
|
||||
/* A concrete event subclass for a purely textual event, for use in
|
||||
|
@ -222,6 +234,7 @@ public:
|
|||
}
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override;
|
||||
meaning get_meaning () const override;
|
||||
|
||||
bool is_function_entry_p () const final override { return true; }
|
||||
};
|
||||
|
@ -241,6 +254,7 @@ public:
|
|||
const program_state &dst_state);
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override;
|
||||
meaning get_meaning () const override;
|
||||
|
||||
function *get_dest_function () const
|
||||
{
|
||||
|
@ -295,6 +309,8 @@ public:
|
|||
class cfg_edge_event : public superedge_event
|
||||
{
|
||||
public:
|
||||
meaning get_meaning () const override;
|
||||
|
||||
const cfg_superedge& get_cfg_superedge () const;
|
||||
|
||||
protected:
|
||||
|
@ -353,6 +369,7 @@ public:
|
|||
location_t loc, tree fndecl, int depth);
|
||||
|
||||
label_text get_desc (bool can_colorize) const override;
|
||||
meaning get_meaning () const override;
|
||||
|
||||
bool is_call_p () const final override;
|
||||
|
||||
|
@ -373,6 +390,7 @@ public:
|
|||
location_t loc, tree fndecl, int depth);
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override;
|
||||
meaning get_meaning () const override;
|
||||
|
||||
bool is_return_p () const final override;
|
||||
|
||||
|
@ -394,6 +412,7 @@ public:
|
|||
}
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override;
|
||||
meaning get_meaning () const override;
|
||||
|
||||
private:
|
||||
bool m_edge_sense;
|
||||
|
@ -521,6 +540,7 @@ public:
|
|||
}
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override;
|
||||
meaning get_meaning () const override;
|
||||
|
||||
private:
|
||||
const state_machine *m_sm;
|
||||
|
|
|
@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
|
||||
#define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
|
||||
|
||||
#include "diagnostic-path.h"
|
||||
|
||||
namespace ana {
|
||||
|
||||
/* A bundle of information about things that are of interest to a
|
||||
|
@ -232,6 +234,15 @@ class pending_diagnostic
|
|||
return label_text ();
|
||||
}
|
||||
|
||||
/* Vfunc for implementing diagnostic_event::get_meaning for
|
||||
state_change_event. */
|
||||
virtual diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &) const
|
||||
{
|
||||
/* Default no-op implementation. */
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
|
||||
/* Precision-of-wording vfunc for describing an interprocedural call
|
||||
carrying critial state for the diagnostic, from caller to callee.
|
||||
|
||||
|
|
|
@ -143,6 +143,20 @@ public:
|
|||
return label_text ();
|
||||
}
|
||||
|
||||
diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &change)
|
||||
const final override
|
||||
{
|
||||
if (change.m_old_state == m_sm.get_start_state ()
|
||||
&& change.m_new_state == m_sm.m_unchecked)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
|
||||
diagnostic_event::NOUN_resource);
|
||||
if (change.m_new_state == m_sm.m_closed)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_release,
|
||||
diagnostic_event::NOUN_resource);
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
|
||||
protected:
|
||||
const fileptr_state_machine &m_sm;
|
||||
tree m_arg;
|
||||
|
|
|
@ -736,6 +736,20 @@ public:
|
|||
return label_text ();
|
||||
}
|
||||
|
||||
diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &change)
|
||||
const final override
|
||||
{
|
||||
if (change.m_old_state == m_sm.get_start_state ()
|
||||
&& unchecked_p (change.m_new_state))
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
|
||||
diagnostic_event::NOUN_memory);
|
||||
if (freed_p (change.m_new_state))
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_release,
|
||||
diagnostic_event::NOUN_memory);
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
|
||||
protected:
|
||||
const malloc_state_machine &m_sm;
|
||||
tree m_arg;
|
||||
|
|
|
@ -117,6 +117,15 @@ public:
|
|||
return label_text ();
|
||||
}
|
||||
|
||||
diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &change)
|
||||
const final override
|
||||
{
|
||||
if (change.m_new_state == m_sm.m_sensitive)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
|
||||
diagnostic_event::NOUN_sensitive);
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
label_text describe_call_with_state (const evdesc::call_with_state &info)
|
||||
final override
|
||||
{
|
||||
|
|
|
@ -163,6 +163,17 @@ public:
|
|||
change.m_expr);
|
||||
return label_text ();
|
||||
}
|
||||
|
||||
diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &change)
|
||||
const final override
|
||||
{
|
||||
if (change.m_new_state == m_sm.m_tainted)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
|
||||
diagnostic_event::NOUN_taint);
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
|
||||
protected:
|
||||
const taint_state_machine &m_sm;
|
||||
tree m_arg;
|
||||
|
|
|
@ -335,6 +335,19 @@ public:
|
|||
return label_text ();
|
||||
}
|
||||
|
||||
diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &change)
|
||||
const final override
|
||||
{
|
||||
if (change.m_new_state == m_sm.m_started)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
|
||||
diagnostic_event::NOUN_resource);
|
||||
if (change.m_new_state == m_sm.m_ended)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_release,
|
||||
diagnostic_event::NOUN_resource);
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
|
||||
protected:
|
||||
va_list_sm_diagnostic (const va_list_state_machine &sm,
|
||||
const svalue *ap_sval, tree ap_tree)
|
||||
|
|
|
@ -46,9 +46,21 @@ enum c_language_kind c_language = clk_c;
|
|||
#undef LANG_HOOKS_GET_SUBSTRING_LOCATION
|
||||
#define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
|
||||
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE c_get_sarif_source_language
|
||||
|
||||
/* Each front end provides its own lang hook initializer. */
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
|
||||
based on the list in SARIF v2.1.0 Appendix J. */
|
||||
|
||||
const char *
|
||||
c_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "c";
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
|
|
@ -837,6 +837,8 @@ set_c_expr_source_range (c_expr *expr,
|
|||
/* In c-fold.cc */
|
||||
extern vec<tree> incomplete_record_decls;
|
||||
|
||||
extern const char *c_get_sarif_source_language (const char *filename);
|
||||
|
||||
#if CHECKING_P
|
||||
namespace selftest {
|
||||
extern void run_c_tests (void);
|
||||
|
|
|
@ -1390,7 +1390,7 @@ Common Joined RejectNegative UInteger
|
|||
|
||||
fdiagnostics-format=
|
||||
Common Joined RejectNegative Enum(diagnostics_output_format)
|
||||
-fdiagnostics-format=[text|json|json-stderr|json-file] Select output format.
|
||||
-fdiagnostics-format=[text|sarif-stderr|sarif-file|json|json-stderr|json-file] Select output format.
|
||||
|
||||
fdiagnostics-escape-format=
|
||||
Common Joined RejectNegative Enum(diagnostics_escape_format)
|
||||
|
@ -1433,6 +1433,12 @@ Enum(diagnostics_output_format) String(json-stderr) Value(DIAGNOSTICS_OUTPUT_FOR
|
|||
EnumValue
|
||||
Enum(diagnostics_output_format) String(json-file) Value(DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE)
|
||||
|
||||
EnumValue
|
||||
Enum(diagnostics_output_format) String(sarif-stderr) Value(DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR)
|
||||
|
||||
EnumValue
|
||||
Enum(diagnostics_output_format) String(sarif-file) Value(DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE)
|
||||
|
||||
fdiagnostics-parseable-fixits
|
||||
Common Var(flag_diagnostics_parseable_fixits)
|
||||
Print fix-it hints in machine-readable form.
|
||||
|
|
|
@ -36,6 +36,7 @@ static tree get_template_argument_pack_elems_folded (const_tree);
|
|||
static tree cxx_enum_underlying_base_type (const_tree);
|
||||
static tree *cxx_omp_get_decl_init (tree);
|
||||
static void cxx_omp_finish_decl_inits (void);
|
||||
static const char *cp_get_sarif_source_language (const char *);
|
||||
|
||||
/* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
|
||||
consequently, there should be very few hooks below. */
|
||||
|
@ -100,6 +101,9 @@ static void cxx_omp_finish_decl_inits (void);
|
|||
#undef LANG_HOOKS_OMP_FINISH_DECL_INITS
|
||||
#define LANG_HOOKS_OMP_FINISH_DECL_INITS cxx_omp_finish_decl_inits
|
||||
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE cp_get_sarif_source_language
|
||||
|
||||
/* Each front end provides its own lang hook initializer. */
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
|
@ -265,6 +269,15 @@ cxx_omp_finish_decl_inits (void)
|
|||
dynamic_initializers = NULL;
|
||||
}
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
|
||||
based on the list in SARIF v2.1.0 Appendix J. */
|
||||
|
||||
static const char *
|
||||
cp_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "cplusplus";
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
|
|
@ -1933,6 +1933,15 @@ d_enum_underlying_base_type (const_tree type)
|
|||
return TREE_TYPE (type);
|
||||
}
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
|
||||
based on the list in SARIF v2.1.0 Appendix J. */
|
||||
|
||||
static const char *
|
||||
d_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "d";
|
||||
}
|
||||
|
||||
/* Definitions for our language-specific hooks. */
|
||||
|
||||
#undef LANG_HOOKS_NAME
|
||||
|
@ -1966,6 +1975,7 @@ d_enum_underlying_base_type (const_tree type)
|
|||
#undef LANG_HOOKS_TYPE_FOR_MODE
|
||||
#undef LANG_HOOKS_TYPE_FOR_SIZE
|
||||
#undef LANG_HOOKS_TYPE_PROMOTES_TO
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
|
||||
#define LANG_HOOKS_NAME "GNU D"
|
||||
#define LANG_HOOKS_INIT d_init
|
||||
|
@ -1998,6 +2008,7 @@ d_enum_underlying_base_type (const_tree type)
|
|||
#define LANG_HOOKS_TYPE_FOR_MODE d_type_for_mode
|
||||
#define LANG_HOOKS_TYPE_FOR_SIZE d_type_for_size
|
||||
#define LANG_HOOKS_TYPE_PROMOTES_TO d_type_promotes_to
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE d_get_sarif_source_language
|
||||
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
|
|
105
gcc/diagnostic-client-data-hooks.h
Normal file
105
gcc/diagnostic-client-data-hooks.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/* Additional metadata about a client for a diagnostic context.
|
||||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H
|
||||
#define GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H
|
||||
|
||||
class client_version_info;
|
||||
|
||||
/* A bundle of additional metadata, owned by the diagnostic_context,
|
||||
for querying things about the client, like version data. */
|
||||
|
||||
class diagnostic_client_data_hooks
|
||||
{
|
||||
public:
|
||||
virtual ~diagnostic_client_data_hooks () {}
|
||||
|
||||
/* Get version info for this client, or NULL. */
|
||||
virtual const client_version_info *get_any_version_info () const = 0;
|
||||
|
||||
/* Get the current logical_location for this client, or NULL. */
|
||||
virtual const logical_location *get_current_logical_location () const = 0;
|
||||
|
||||
/* Get a sourceLanguage value for FILENAME, or return NULL.
|
||||
See SARIF v2.1.0 Appendix J for suggested values. */
|
||||
virtual const char *
|
||||
maybe_get_sarif_source_language (const char *filename) const = 0;
|
||||
};
|
||||
|
||||
/* Factory function for making an instance of diagnostic_client_data_hooks
|
||||
for use in the compiler (i.e. with knowledge of "tree", access to
|
||||
langhooks, etc). */
|
||||
|
||||
extern diagnostic_client_data_hooks *make_compiler_data_hooks ();
|
||||
|
||||
class diagnostic_client_plugin_info;
|
||||
|
||||
/* Abstract base class for a diagnostic_context to get at
|
||||
version information about the client. */
|
||||
|
||||
class client_version_info
|
||||
{
|
||||
public:
|
||||
class plugin_visitor
|
||||
{
|
||||
public:
|
||||
virtual void on_plugin (const diagnostic_client_plugin_info &) = 0;
|
||||
};
|
||||
|
||||
virtual ~client_version_info () {}
|
||||
|
||||
/* Get a string suitable for use as the value of the "name" property
|
||||
(SARIF v2.1.0 section 3.19.8). */
|
||||
virtual const char *get_tool_name () const = 0;
|
||||
|
||||
/* Create a string suitable for use as the value of the "fullName" property
|
||||
(SARIF v2.1.0 section 3.19.9). */
|
||||
virtual char *maybe_make_full_name () const = 0;
|
||||
|
||||
/* Get a string suitable for use as the value of the "version" property
|
||||
(SARIF v2.1.0 section 3.19.13). */
|
||||
virtual const char *get_version_string () const = 0;
|
||||
|
||||
/* Create a string suitable for use as the value of the "informationUri"
|
||||
property (SARIF v2.1.0 section 3.19.17). */
|
||||
virtual char *maybe_make_version_url () const = 0;
|
||||
|
||||
virtual void for_each_plugin (plugin_visitor &v) const = 0;
|
||||
};
|
||||
|
||||
/* Abstract base class for a diagnostic_context to get at
|
||||
information about a specific plugin within a client. */
|
||||
|
||||
class diagnostic_client_plugin_info
|
||||
{
|
||||
public:
|
||||
/* For use e.g. by SARIF "name" property (SARIF v2.1.0 section 3.19.8). */
|
||||
virtual const char *get_short_name () const = 0;
|
||||
|
||||
/* For use e.g. by SARIF "fullName" property
|
||||
(SARIF v2.1.0 section 3.19.9). */
|
||||
virtual const char *get_full_name () const = 0;
|
||||
|
||||
/* For use e.g. by SARIF "version" property
|
||||
(SARIF v2.1.0 section 3.19.13). */
|
||||
virtual const char *get_version () const = 0;
|
||||
};
|
||||
|
||||
#endif /* ! GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H */
|
1586
gcc/diagnostic-format-sarif.cc
Normal file
1586
gcc/diagnostic-format-sarif.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -69,6 +69,75 @@ along with GCC; see the file COPYING3. If not see
|
|||
class diagnostic_event
|
||||
{
|
||||
public:
|
||||
/* Enums for giving a sense of what this event means.
|
||||
Roughly corresponds to SARIF v2.1.0 section 3.38.8. */
|
||||
enum verb
|
||||
{
|
||||
VERB_unknown,
|
||||
|
||||
VERB_acquire,
|
||||
VERB_release,
|
||||
VERB_enter,
|
||||
VERB_exit,
|
||||
VERB_call,
|
||||
VERB_return,
|
||||
VERB_branch,
|
||||
|
||||
VERB_danger
|
||||
};
|
||||
enum noun
|
||||
{
|
||||
NOUN_unknown,
|
||||
|
||||
NOUN_taint,
|
||||
NOUN_sensitive, // this one isn't in SARIF v2.1.0; filed as https://github.com/oasis-tcs/sarif-spec/issues/530
|
||||
NOUN_function,
|
||||
NOUN_lock,
|
||||
NOUN_memory,
|
||||
NOUN_resource
|
||||
};
|
||||
enum property
|
||||
{
|
||||
PROPERTY_unknown,
|
||||
|
||||
PROPERTY_true,
|
||||
PROPERTY_false
|
||||
};
|
||||
/* A bundle of such enums, allowing for descriptions of the meaning of
|
||||
an event, such as
|
||||
- "acquire memory": meaning (VERB_acquire, NOUN_memory)
|
||||
- "take true branch"": meaning (VERB_branch, PROPERTY_true)
|
||||
- "return from function": meaning (VERB_return, NOUN_function)
|
||||
etc, as per SARIF's threadFlowLocation "kinds" property
|
||||
(SARIF v2.1.0 section 3.38.8). */
|
||||
struct meaning
|
||||
{
|
||||
meaning ()
|
||||
: m_verb (VERB_unknown),
|
||||
m_noun (NOUN_unknown),
|
||||
m_property (PROPERTY_unknown)
|
||||
{
|
||||
}
|
||||
meaning (enum verb verb, enum noun noun)
|
||||
: m_verb (verb), m_noun (noun), m_property (PROPERTY_unknown)
|
||||
{
|
||||
}
|
||||
meaning (enum verb verb, enum property property)
|
||||
: m_verb (verb), m_noun (NOUN_unknown), m_property (property)
|
||||
{
|
||||
}
|
||||
|
||||
void dump_to_pp (pretty_printer *pp) const;
|
||||
|
||||
static const char *maybe_get_verb_str (enum verb);
|
||||
static const char *maybe_get_noun_str (enum noun);
|
||||
static const char *maybe_get_property_str (enum property);
|
||||
|
||||
enum verb m_verb;
|
||||
enum noun m_noun;
|
||||
enum property m_property;
|
||||
};
|
||||
|
||||
virtual ~diagnostic_event () {}
|
||||
|
||||
virtual location_t get_location () const = 0;
|
||||
|
@ -81,6 +150,11 @@ class diagnostic_event
|
|||
|
||||
/* Get a localized (and possibly colorized) description of this event. */
|
||||
virtual label_text get_desc (bool can_colorize) const = 0;
|
||||
|
||||
/* Get a logical_location for this event, or NULL. */
|
||||
virtual const logical_location *get_logical_location () const = 0;
|
||||
|
||||
virtual meaning get_meaning () const = 0;
|
||||
};
|
||||
|
||||
/* Abstract base class for getting at a sequence of events. */
|
||||
|
@ -113,6 +187,14 @@ class simple_diagnostic_event : public diagnostic_event
|
|||
{
|
||||
return label_text::borrow (m_desc);
|
||||
}
|
||||
const logical_location *get_logical_location () const final override
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
meaning get_meaning () const final override
|
||||
{
|
||||
return meaning ();
|
||||
}
|
||||
|
||||
private:
|
||||
location_t m_loc;
|
||||
|
|
|
@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "diagnostic-url.h"
|
||||
#include "diagnostic-metadata.h"
|
||||
#include "diagnostic-path.h"
|
||||
#include "diagnostic-client-data-hooks.h"
|
||||
#include "edit-context.h"
|
||||
#include "selftest.h"
|
||||
#include "selftest-diagnostic.h"
|
||||
|
@ -240,6 +241,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
|
|||
context->end_group_cb = NULL;
|
||||
context->final_cb = default_diagnostic_final_cb;
|
||||
context->includes_seen = NULL;
|
||||
context->m_client_data_hooks = NULL;
|
||||
}
|
||||
|
||||
/* Maybe initialize the color support. We require clients to do this
|
||||
|
@ -338,6 +340,12 @@ diagnostic_finish (diagnostic_context *context)
|
|||
delete context->includes_seen;
|
||||
context->includes_seen = nullptr;
|
||||
}
|
||||
|
||||
if (context->m_client_data_hooks)
|
||||
{
|
||||
delete context->m_client_data_hooks;
|
||||
context->m_client_data_hooks = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize DIAGNOSTIC, where the message MSG has already been
|
||||
|
@ -820,6 +828,116 @@ diagnostic_show_any_path (diagnostic_context *context,
|
|||
context->print_path (context, path);
|
||||
}
|
||||
|
||||
/* class diagnostic_event. */
|
||||
|
||||
/* struct diagnostic_event::meaning. */
|
||||
|
||||
void
|
||||
diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
|
||||
{
|
||||
bool need_comma = false;
|
||||
pp_character (pp, '{');
|
||||
if (const char *verb_str = maybe_get_verb_str (m_verb))
|
||||
{
|
||||
pp_printf (pp, "verb: %qs", verb_str);
|
||||
need_comma = true;
|
||||
}
|
||||
if (const char *noun_str = maybe_get_noun_str (m_noun))
|
||||
{
|
||||
if (need_comma)
|
||||
pp_string (pp, ", ");
|
||||
pp_printf (pp, "noun: %qs", noun_str);
|
||||
need_comma = true;
|
||||
}
|
||||
if (const char *property_str = maybe_get_property_str (m_property))
|
||||
{
|
||||
if (need_comma)
|
||||
pp_string (pp, ", ");
|
||||
pp_printf (pp, "property: %qs", property_str);
|
||||
need_comma = true;
|
||||
}
|
||||
pp_character (pp, '}');
|
||||
}
|
||||
|
||||
/* Get a string (or NULL) for V suitable for use within a SARIF
|
||||
threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
|
||||
|
||||
const char *
|
||||
diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
|
||||
{
|
||||
switch (v)
|
||||
{
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
case VERB_unknown:
|
||||
return NULL;
|
||||
case VERB_acquire:
|
||||
return "acquire";
|
||||
case VERB_release:
|
||||
return "release";
|
||||
case VERB_enter:
|
||||
return "enter";
|
||||
case VERB_exit:
|
||||
return "exit";
|
||||
case VERB_call:
|
||||
return "call";
|
||||
case VERB_return:
|
||||
return "return";
|
||||
case VERB_branch:
|
||||
return "branch";
|
||||
case VERB_danger:
|
||||
return "danger";
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a string (or NULL) for N suitable for use within a SARIF
|
||||
threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
|
||||
|
||||
const char *
|
||||
diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
case NOUN_unknown:
|
||||
return NULL;
|
||||
case NOUN_taint:
|
||||
return "taint";
|
||||
case NOUN_sensitive:
|
||||
return "sensitive";
|
||||
case NOUN_function:
|
||||
return "function";
|
||||
case NOUN_lock:
|
||||
return "lock";
|
||||
case NOUN_memory:
|
||||
return "memory";
|
||||
case NOUN_resource:
|
||||
return "resource";
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a string (or NULL) for P suitable for use within a SARIF
|
||||
threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
|
||||
|
||||
const char *
|
||||
diagnostic_event::meaning::maybe_get_property_str (enum property p)
|
||||
{
|
||||
switch (p)
|
||||
{
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
case PROPERTY_unknown:
|
||||
return NULL;
|
||||
case PROPERTY_true:
|
||||
return "true";
|
||||
case PROPERTY_false:
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
|
||||
/* class diagnostic_path. */
|
||||
|
||||
/* Return true if the events in this path involve more than one
|
||||
function, or false if it is purely intraprocedural. */
|
||||
|
||||
|
@ -1131,7 +1249,7 @@ update_effective_level_from_pragmas (diagnostic_context *context,
|
|||
/* Generate a URL string describing CWE. The caller is responsible for
|
||||
freeing the string. */
|
||||
|
||||
static char *
|
||||
char *
|
||||
get_cwe_url (int cwe)
|
||||
{
|
||||
return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
|
||||
|
@ -2095,6 +2213,14 @@ diagnostic_output_format_init (diagnostic_context *context,
|
|||
case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
|
||||
diagnostic_output_format_init_json_file (context, base_file_name);
|
||||
break;
|
||||
|
||||
case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
|
||||
diagnostic_output_format_init_sarif_stderr (context);
|
||||
break;
|
||||
|
||||
case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
|
||||
diagnostic_output_format_init_sarif_file (context, base_file_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,13 @@ enum diagnostics_output_format
|
|||
DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR,
|
||||
|
||||
/* JSON-based output, to a file. */
|
||||
DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE
|
||||
DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE,
|
||||
|
||||
/* SARIF-based output, to stderr. */
|
||||
DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR,
|
||||
|
||||
/* SARIF-based output, to a file. */
|
||||
DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
|
||||
};
|
||||
|
||||
/* An enum for controlling how diagnostic_paths should be printed. */
|
||||
|
@ -162,6 +168,8 @@ typedef void (*diagnostic_finalizer_fn) (diagnostic_context *,
|
|||
|
||||
class edit_context;
|
||||
namespace json { class value; }
|
||||
class diagnostic_client_data_hooks;
|
||||
class logical_location;
|
||||
|
||||
/* This data structure bundles altogether any information relevant to
|
||||
the context of a diagnostic message. */
|
||||
|
@ -397,6 +405,12 @@ struct diagnostic_context
|
|||
/* Include files that diagnostic_report_current_module has already listed the
|
||||
include path for. */
|
||||
hash_set<location_t, false, location_hash> *includes_seen;
|
||||
|
||||
/* A bundle of hooks for providing data to the context about its client
|
||||
e.g. version information, plugins, etc.
|
||||
Used by SARIF output to give metadata about the client that's
|
||||
producing diagnostics. */
|
||||
diagnostic_client_data_hooks *m_client_data_hooks;
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
@ -585,6 +599,9 @@ extern void diagnostic_output_format_init (diagnostic_context *,
|
|||
extern void diagnostic_output_format_init_json_stderr (diagnostic_context *context);
|
||||
extern void diagnostic_output_format_init_json_file (diagnostic_context *context,
|
||||
const char *base_file_name);
|
||||
extern void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context);
|
||||
extern void diagnostic_output_format_init_sarif_file (diagnostic_context *context,
|
||||
const char *base_file_name);
|
||||
|
||||
/* Compute the number of digits in the decimal representation of an integer. */
|
||||
extern int num_digits (int);
|
||||
|
@ -594,4 +611,6 @@ extern json::value *json_from_expanded_location (diagnostic_context *context,
|
|||
|
||||
extern bool warning_enabled_at (location_t, int);
|
||||
|
||||
extern char *get_cwe_url (int cwe);
|
||||
|
||||
#endif /* ! GCC_DIAGNOSTIC_H */
|
||||
|
|
|
@ -301,7 +301,7 @@ Objective-C and Objective-C++ Dialects}.
|
|||
-fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol
|
||||
-fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]} @gol
|
||||
-fdiagnostics-urls=@r{[}auto@r{|}never@r{|}always@r{]} @gol
|
||||
-fdiagnostics-format=@r{[}text@r{|}json@r{|}json-stderr@r{|}json-file@r{]} @gol
|
||||
-fdiagnostics-format=@r{[}text@r{|}sarif-stderr@r{|}sarif-file@r{|}json@r{|}json-stderr@r{|}json-file@r{]} @gol
|
||||
-fno-diagnostics-show-option -fno-diagnostics-show-caret @gol
|
||||
-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers @gol
|
||||
-fno-diagnostics-show-cwe @gol
|
||||
|
@ -5305,11 +5305,15 @@ Unicode characters. For the example above, the following will be printed:
|
|||
@item -fdiagnostics-format=@var{FORMAT}
|
||||
@opindex fdiagnostics-format
|
||||
Select a different format for printing diagnostics.
|
||||
@var{FORMAT} is @samp{text}, @samp{json}, @samp{json-stderr},
|
||||
or @samp{json-file}.
|
||||
@var{FORMAT} is @samp{text}, @samp{sarif-stderr}, @samp{sarif-file},
|
||||
@samp{json}, @samp{json-stderr}, or @samp{json-file}.
|
||||
|
||||
The default is @samp{text}.
|
||||
|
||||
The @samp{sarif-stderr} and @samp{sarif-file} formats both emit
|
||||
diagnostics in SARIF Version 2.1.0 format, either to stderr, or to a file
|
||||
named @file{@var{source}.sarif}, respectively.
|
||||
|
||||
The @samp{json} format is a synonym for @samp{json-stderr}.
|
||||
The @samp{json-stderr} and @samp{json-file} formats are identical, apart from
|
||||
where the JSON is emitted to - with the former, the JSON is emitted to stderr,
|
||||
|
|
|
@ -3152,6 +3152,12 @@ Passes if @var{regexp} matches in Fortran module @var{module}.
|
|||
@item dg-check-dot @var{filename}
|
||||
Passes if @var{filename} is a valid @file{.dot} file (by running
|
||||
@code{dot -Tpng} on it, and verifying the exit code is 0).
|
||||
@item scan-sarif-file @var{regexp} [@{ target/xfail @var{selector} @}]
|
||||
Passes if @var{regexp} matches text in the file generated by
|
||||
@option{-fdiagnostics-format=sarif-file}.
|
||||
@item scan-sarif-file-not @var{regexp} [@{ target/xfail @var{selector} @}]
|
||||
Passes if @var{regexp} does not match text in the file generated by
|
||||
@option{-fdiagnostics-format=sarif-file}.
|
||||
@end table
|
||||
|
||||
@subsubsection Scan the assembly output
|
||||
|
|
|
@ -100,6 +100,15 @@ static const struct attribute_spec gfc_attribute_table[] =
|
|||
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
|
||||
};
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
|
||||
based on the list in SARIF v2.1.0 Appendix J. */
|
||||
|
||||
static const char *
|
||||
gfc_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "fortran";
|
||||
}
|
||||
|
||||
#undef LANG_HOOKS_NAME
|
||||
#undef LANG_HOOKS_INIT
|
||||
#undef LANG_HOOKS_FINISH
|
||||
|
@ -138,6 +147,7 @@ static const struct attribute_spec gfc_attribute_table[] =
|
|||
#undef LANG_HOOKS_BUILTIN_FUNCTION
|
||||
#undef LANG_HOOKS_GET_ARRAY_DESCR_INFO
|
||||
#undef LANG_HOOKS_ATTRIBUTE_TABLE
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
|
||||
/* Define lang hooks. */
|
||||
#define LANG_HOOKS_NAME "GNU Fortran"
|
||||
|
@ -177,6 +187,7 @@ static const struct attribute_spec gfc_attribute_table[] =
|
|||
#define LANG_HOOKS_BUILTIN_FUNCTION gfc_builtin_function
|
||||
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO gfc_get_array_descr_info
|
||||
#define LANG_HOOKS_ATTRIBUTE_TABLE gfc_attribute_table
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE gfc_get_sarif_source_language
|
||||
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
|
|
|
@ -545,6 +545,15 @@ go_langhook_eh_personality (void)
|
|||
return personality_decl;
|
||||
}
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
|
||||
based on the list in SARIF v2.1.0 Appendix J. */
|
||||
|
||||
static const char *
|
||||
go_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "go";
|
||||
}
|
||||
|
||||
/* Functions called directly by the generic backend. */
|
||||
|
||||
tree
|
||||
|
@ -615,6 +624,7 @@ go_localize_identifier (const char *ident)
|
|||
#undef LANG_HOOKS_GETDECLS
|
||||
#undef LANG_HOOKS_GIMPLIFY_EXPR
|
||||
#undef LANG_HOOKS_EH_PERSONALITY
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
|
||||
#define LANG_HOOKS_NAME "GNU Go"
|
||||
#define LANG_HOOKS_INIT go_langhook_init
|
||||
|
@ -631,6 +641,7 @@ go_localize_identifier (const char *ident)
|
|||
#define LANG_HOOKS_GETDECLS go_langhook_getdecls
|
||||
#define LANG_HOOKS_GIMPLIFY_EXPR go_langhook_gimplify_expr
|
||||
#define LANG_HOOKS_EH_PERSONALITY go_langhook_eh_personality
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE go_get_sarif_source_language
|
||||
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ extern const char *lhd_get_substring_location (const substring_loc &,
|
|||
extern int lhd_decl_dwarf_attribute (const_tree, int);
|
||||
extern int lhd_type_dwarf_attribute (const_tree, int);
|
||||
extern void lhd_finalize_early_debug (void);
|
||||
extern const char *lhd_get_sarif_source_language (const char *);
|
||||
|
||||
#define LANG_HOOKS_NAME "GNU unknown"
|
||||
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
|
||||
|
@ -150,6 +151,7 @@ extern void lhd_finalize_early_debug (void);
|
|||
#define LANG_HOOKS_RUN_LANG_SELFTESTS lhd_do_nothing
|
||||
#define LANG_HOOKS_GET_SUBSTRING_LOCATION lhd_get_substring_location
|
||||
#define LANG_HOOKS_FINALIZE_EARLY_DEBUG lhd_finalize_early_debug
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE lhd_get_sarif_source_language
|
||||
|
||||
/* Attribute hooks. */
|
||||
#define LANG_HOOKS_ATTRIBUTE_TABLE NULL
|
||||
|
@ -394,7 +396,8 @@ extern void lhd_end_section (void);
|
|||
LANG_HOOKS_EMITS_BEGIN_STMT, \
|
||||
LANG_HOOKS_RUN_LANG_SELFTESTS, \
|
||||
LANG_HOOKS_GET_SUBSTRING_LOCATION, \
|
||||
LANG_HOOKS_FINALIZE_EARLY_DEBUG \
|
||||
LANG_HOOKS_FINALIZE_EARLY_DEBUG, \
|
||||
LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE \
|
||||
}
|
||||
|
||||
#endif /* GCC_LANG_HOOKS_DEF_H */
|
||||
|
|
|
@ -925,6 +925,14 @@ lhd_finalize_early_debug (void)
|
|||
(*debug_hooks->early_global_decl) (cnode->decl);
|
||||
}
|
||||
|
||||
/* Default implementation of LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE. */
|
||||
|
||||
const char *
|
||||
lhd_get_sarif_source_language (const char *)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns true if the current lang_hooks represents the GNU C frontend. */
|
||||
|
||||
bool
|
||||
|
|
|
@ -640,6 +640,12 @@ struct lang_hooks
|
|||
/* Invoked before the early_finish debug hook is invoked. */
|
||||
void (*finalize_early_debug) (void);
|
||||
|
||||
/* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property
|
||||
for FILENAME, or return NULL.
|
||||
See SARIF v2.1.0 Appendix J for suggested values for common programming
|
||||
languages. */
|
||||
const char *(*get_sarif_source_language) (const char *filename);
|
||||
|
||||
/* Whenever you add entries here, make sure you adjust langhooks-def.h
|
||||
and langhooks.cc accordingly. */
|
||||
};
|
||||
|
|
72
gcc/logical-location.h
Normal file
72
gcc/logical-location.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Logical location support, without knowledge of "tree".
|
||||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_LOGICAL_LOCATION_H
|
||||
#define GCC_LOGICAL_LOCATION_H
|
||||
|
||||
/* An enum for discriminating between different kinds of logical location
|
||||
for a diagnostic.
|
||||
|
||||
Roughly corresponds to logicalLocation's "kind" property in SARIF v2.1.0
|
||||
(section 3.33.7). */
|
||||
|
||||
enum logical_location_kind
|
||||
{
|
||||
LOGICAL_LOCATION_KIND_UNKNOWN,
|
||||
|
||||
LOGICAL_LOCATION_KIND_FUNCTION,
|
||||
LOGICAL_LOCATION_KIND_MEMBER,
|
||||
LOGICAL_LOCATION_KIND_MODULE,
|
||||
LOGICAL_LOCATION_KIND_NAMESPACE,
|
||||
LOGICAL_LOCATION_KIND_TYPE,
|
||||
LOGICAL_LOCATION_KIND_RETURN_TYPE,
|
||||
LOGICAL_LOCATION_KIND_PARAMETER,
|
||||
LOGICAL_LOCATION_KIND_VARIABLE
|
||||
};
|
||||
|
||||
/* Abstract base class for passing around logical locations in the
|
||||
diagnostics subsystem, such as:
|
||||
- "within function 'foo'", or
|
||||
- "within method 'bar'",
|
||||
but *without* requiring knowledge of trees
|
||||
(see tree-logical-location.h for subclasses relating to trees). */
|
||||
|
||||
class logical_location
|
||||
{
|
||||
public:
|
||||
virtual ~logical_location () {}
|
||||
|
||||
/* Get a string (or NULL) suitable for use by the SARIF logicalLocation
|
||||
"name" property (SARIF v2.1.0 section 3.33.4). */
|
||||
virtual const char *get_short_name () const = 0;
|
||||
|
||||
/* Get a string (or NULL) suitable for use by the SARIF logicalLocation
|
||||
"fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5). */
|
||||
virtual const char *get_name_with_scope () const = 0;
|
||||
|
||||
/* Get a string (or NULL) suitable for use by the SARIF logicalLocation
|
||||
"decoratedName" property (SARIF v2.1.0 section 3.33.6). */
|
||||
virtual const char *get_internal_name () const = 0;
|
||||
|
||||
/* Get what kind of SARIF logicalLocation this is (if any). */
|
||||
virtual enum logical_location_kind get_kind () const = 0;
|
||||
};
|
||||
|
||||
#endif /* GCC_LOGICAL_LOCATION_H. */
|
|
@ -27,6 +27,7 @@ bool objc_init (void);
|
|||
const char *objc_printable_name (tree, int);
|
||||
int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
|
||||
void objc_common_init_ts (void);
|
||||
const char *objc_get_sarif_source_language (const char *);
|
||||
|
||||
/* NB: The remaining public functions are prototyped in c-common.h, for the
|
||||
benefit of stub-objc.cc and objc-act.cc. */
|
||||
|
|
|
@ -46,10 +46,18 @@ enum c_language_kind c_language = clk_objc;
|
|||
#define LANG_HOOKS_INIT_TS objc_common_init_ts
|
||||
#undef LANG_HOOKS_TREE_SIZE
|
||||
#define LANG_HOOKS_TREE_SIZE objc_common_tree_size
|
||||
#undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
|
||||
#define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE objc_get_sarif_source_language
|
||||
|
||||
/* Each front end provides its own lang hook initializer. */
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
const char *
|
||||
objc_get_sarif_source_language (const char *)
|
||||
{
|
||||
return "objectivec";
|
||||
}
|
||||
|
||||
/* Lang hook routines common to C and ObjC appear in c-objc-common.cc;
|
||||
there should be very few (if any) routines below. */
|
||||
|
||||
|
|
|
@ -815,6 +815,44 @@ finalize_plugins (void)
|
|||
plugin_name_args_tab = NULL;
|
||||
}
|
||||
|
||||
/* Implementation detail of for_each_plugin. */
|
||||
|
||||
struct for_each_plugin_closure
|
||||
{
|
||||
void (*cb) (const plugin_name_args *,
|
||||
void *user_data);
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/* Implementation detail of for_each_plugin: callback for htab_traverse_noresize
|
||||
that calls the user-provided callback. */
|
||||
|
||||
static int
|
||||
for_each_plugin_cb (void **slot, void *info)
|
||||
{
|
||||
struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
|
||||
for_each_plugin_closure *c = (for_each_plugin_closure *)info;
|
||||
c->cb (plugin, c->user_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Call CB with USER_DATA on each plugin. */
|
||||
|
||||
void
|
||||
for_each_plugin (void (*cb) (const plugin_name_args *,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
if (!plugin_name_args_tab)
|
||||
return;
|
||||
|
||||
for_each_plugin_closure c;
|
||||
c.cb = cb;
|
||||
c.user_data = user_data;
|
||||
|
||||
htab_traverse_noresize (plugin_name_args_tab, for_each_plugin_cb, &c);
|
||||
}
|
||||
|
||||
/* Used to pass options to htab_traverse callbacks. */
|
||||
|
||||
struct print_options
|
||||
|
|
|
@ -170,6 +170,9 @@ extern void warn_if_plugins (void);
|
|||
extern void print_plugins_versions (FILE *file, const char *indent);
|
||||
extern void print_plugins_help (FILE *file, const char *indent);
|
||||
extern void finalize_plugins (void);
|
||||
extern void for_each_plugin (void (*cb) (const plugin_name_args *,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
extern bool flag_plugin_added;
|
||||
|
||||
|
|
43
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
Normal file
43
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdiagnostics-format=sarif-file" } */
|
||||
|
||||
#warning message
|
||||
|
||||
/* Verify that some JSON was written to a file with the expected name. */
|
||||
|
||||
/* We expect various properties.
|
||||
The indentation here reflects the expected hierarchy, though these tests
|
||||
don't check for that, merely the string fragments we expect.
|
||||
{ dg-final { scan-sarif-file "\"version\": \"2.1.0\"" } }
|
||||
{ dg-final { scan-sarif-file "\"runs\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"artifacts\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"location\": " } }
|
||||
{ dg-final { scan-sarif-file "\"uri\": " } }
|
||||
|
||||
{ dg-final { scan-sarif-file "\"sourceLanguage\": \"c\"" { target c } } }
|
||||
{ dg-final { scan-sarif-file "\"sourceLanguage\": \"cplusplus\"" { target c++ } } }
|
||||
|
||||
{ dg-final { scan-sarif-file "\"contents\": " } }
|
||||
{ dg-final { scan-sarif-file "\"text\": " } }
|
||||
{ dg-final { scan-sarif-file "\"tool\": " } }
|
||||
{ dg-final { scan-sarif-file "\"driver\": " } }
|
||||
{ dg-final { scan-sarif-file "\"name\": \"GNU C" } }
|
||||
{ dg-final { scan-sarif-file "\"fullName\": \"GNU C" } }
|
||||
{ dg-final { scan-sarif-file "\"informationUri\": \"" } }
|
||||
{ dg-final { scan-sarif-file "\"results\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"level\": \"warning\"" } }
|
||||
{ dg-final { scan-sarif-file "\"ruleId\": \"-Wcpp\"" } }
|
||||
{ dg-final { scan-sarif-file "\"locations\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"physicalLocation\": " } }
|
||||
{ dg-final { scan-sarif-file "\"contextRegion\": " } }
|
||||
{ dg-final { scan-sarif-file "\"artifactLocation\": " } }
|
||||
{ dg-final { scan-sarif-file "\"region\": " } }
|
||||
{ dg-final { scan-sarif-file "\"startLine\": 4" } }
|
||||
{ dg-final { scan-sarif-file "\"startColumn\": 2" } }
|
||||
{ dg-final { scan-sarif-file "\"endColumn\": 9" } }
|
||||
|
||||
We don't expect logical locations for a top-level warning:
|
||||
{ dg-final { scan-sarif-file-not "\"logicalLocations\": " } }
|
||||
|
||||
{ dg-final { scan-sarif-file "\"message\": " } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \"#warning message" } } */
|
29
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-2.c
Normal file
29
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdiagnostics-format=sarif-file -Wmisleading-indentation" } */
|
||||
|
||||
int test (void)
|
||||
{
|
||||
if (1)
|
||||
return 3;
|
||||
return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
/*
|
||||
{ dg-final { scan-sarif-file "\"level\": \"warning\"" } }
|
||||
{ dg-final { scan-sarif-file "\"ruleId\": \"-Wmisleading-indentation\"" } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \" if " } }
|
||||
|
||||
{ dg-final { scan-sarif-file "\"locations\": \\\[" } }
|
||||
|
||||
We expect a logical location for the error (within fn "test"):
|
||||
{ dg-final { scan-sarif-file "\"logicalLocations\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"kind\": \"function\"" } }
|
||||
{ dg-final { scan-sarif-file "\"name\": \"test\"" } }
|
||||
{ dg-final { scan-sarif-file "\"fullyQualifiedName\": \"test\"" } }
|
||||
{ dg-final { scan-sarif-file "\"decoratedName\": \"" } }
|
||||
|
||||
We expect the "note" to become a "relatedLocations" entry:
|
||||
{ dg-final { scan-sarif-file "\"relatedLocations\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \" return 4;" } }
|
||||
*/
|
30
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-3.c
Normal file
30
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-3.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdiagnostics-format=sarif-file" } */
|
||||
/* { dg-excess-errors "The error is sent to the SARIF file, rather than stderr" } */
|
||||
|
||||
struct s { int color; };
|
||||
|
||||
int test (struct s *ptr)
|
||||
{
|
||||
return ptr->colour;
|
||||
}
|
||||
|
||||
/*
|
||||
{ dg-final { scan-sarif-file "\"level\": \"error\"" } }
|
||||
|
||||
We expect a logical location for the error (within fn "test"):
|
||||
{ dg-final { scan-sarif-file "\"locations\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"logicalLocations\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"kind\": \"function\"" } }
|
||||
{ dg-final { scan-sarif-file "\"name\": \"test\"" } }
|
||||
{ dg-final { scan-sarif-file "\"fullyQualifiedName\": \"test\"" } }
|
||||
{ dg-final { scan-sarif-file "\"decoratedName\": \"" } }
|
||||
|
||||
We expect a "fixes" array for the fix-it hint (SARIF v2.1.0 section 3.27.30):
|
||||
{ dg-final { scan-sarif-file "\"fixes\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"artifactChanges\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"replacements\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"insertedContent\": " } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \"color\"" } }
|
||||
{ dg-final { scan-sarif-file "\"deletedRegion\": " } }
|
||||
*/
|
19
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-4.c
Normal file
19
gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-4.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdiagnostics-format=sarif-file" } */
|
||||
/* { dg-excess-errors "The error is sent to the SARIF file, rather than stderr" } */
|
||||
|
||||
int test (void)
|
||||
{
|
||||
int 文字化け = *42;
|
||||
}
|
||||
|
||||
/*
|
||||
{ dg-final { scan-sarif-file "\"level\": \"error\"" } }
|
||||
|
||||
We expect the region expressed in display columns:
|
||||
{ dg-final { scan-sarif-file "\"startLine\": 7" } }
|
||||
{ dg-final { scan-sarif-file "\"startColumn\": 18" } }
|
||||
{ dg-final { scan-sarif-file "\"endColumn\": 21" } }
|
||||
|
||||
{ dg-final { scan-sarif-file "\"text\": \" int \\u6587\\u5b57\\u5316\\u3051 = " } }
|
||||
*/
|
15
gcc/testsuite/gcc.dg/analyzer/file-meaning-1.c
Normal file
15
gcc/testsuite/gcc.dg/analyzer/file-meaning-1.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-additional-options "-fanalyzer-verbose-state-changes" } */
|
||||
|
||||
typedef struct FILE FILE;
|
||||
FILE* fopen (const char*, const char*);
|
||||
int fclose (FILE*);
|
||||
|
||||
void test_1 (const char *path)
|
||||
{
|
||||
FILE *f = fopen (path, "r"); /* { dg-message "meaning: \\{verb: 'acquire', noun: 'resource'\\}" } */
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
fclose (f); /* { dg-message "meaning: \\{verb: 'release', noun: 'resource'\\}" } */
|
||||
fclose (f); /* { dg-warning "double 'fclose' of FILE 'f'" "warning" } */
|
||||
}
|
10
gcc/testsuite/gcc.dg/analyzer/malloc-meaning-1.c
Normal file
10
gcc/testsuite/gcc.dg/analyzer/malloc-meaning-1.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* { dg-additional-options "-fanalyzer-verbose-state-changes" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void test_1 (void)
|
||||
{
|
||||
void *ptr = malloc (1024); /* { dg-message "meaning: \\{verb: 'acquire', noun: 'memory'\\}" } */
|
||||
free (ptr); /* { dg-message "meaning: \\{verb: 'release', noun: 'memory'\\}" } */
|
||||
free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
|
||||
}
|
20
gcc/testsuite/gcc.dg/analyzer/malloc-sarif-1.c
Normal file
20
gcc/testsuite/gcc.dg/analyzer/malloc-sarif-1.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-fdiagnostics-format=sarif-file" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void test_1 (void)
|
||||
{
|
||||
void *ptr = malloc (1024);
|
||||
free (ptr);
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
/* Verify SARIF output.
|
||||
|
||||
The threadFlowLocation objects should have "kinds" properties
|
||||
reflecting the meanings of the events:
|
||||
{ dg-final { scan-sarif-file "\"kinds\": \\\[\"acquire\", \"memory\"\\\]" } }
|
||||
{ dg-final { scan-sarif-file "\"kinds\": \\\[\"release\", \"memory\"\\\]" } }
|
||||
{ dg-final { scan-sarif-file "\"kinds\": \\\[\"danger\"\\\]" } }
|
||||
*/
|
|
@ -109,6 +109,21 @@ public:
|
|||
return label_text ();
|
||||
}
|
||||
|
||||
diagnostic_event::meaning
|
||||
get_meaning_for_state_change (const evdesc::state_change &change)
|
||||
const final override
|
||||
{
|
||||
if (change.is_global_p ())
|
||||
{
|
||||
if (change.m_new_state == m_sm.m_released_gil)
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_release,
|
||||
diagnostic_event::NOUN_lock);
|
||||
else if (change.m_new_state == m_sm.get_start_state ())
|
||||
return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
|
||||
diagnostic_event::NOUN_lock);
|
||||
}
|
||||
return diagnostic_event::meaning ();
|
||||
}
|
||||
protected:
|
||||
gil_diagnostic (const gil_state_machine &sm) : m_sm (sm)
|
||||
{
|
||||
|
|
56
gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-5.c
Normal file
56
gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-5.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdiagnostics-format=sarif-file" } */
|
||||
/* { dg-excess-errors "The error is sent to the SARIF file, rather than stderr" } */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Minimal reimplementation of cpython API. */
|
||||
typedef struct PyObject {} PyObject;
|
||||
extern int PyArg_ParseTuple (PyObject *args, const char *fmt, ...);
|
||||
extern PyObject *PyList_New (int);
|
||||
extern PyObject *PyLong_FromLong(long);
|
||||
extern void PyList_Append(PyObject *list, PyObject *item);
|
||||
|
||||
PyObject *
|
||||
make_a_list_of_random_ints_badly(PyObject *self,
|
||||
PyObject *args)
|
||||
{
|
||||
PyObject *list, *item;
|
||||
long count, i;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &count)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list = PyList_New(0);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
item = PyLong_FromLong(random());
|
||||
PyList_Append(list, item);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
{ dg-final { scan-sarif-file "\"tool\": " } }
|
||||
|
||||
We expect info about the plugin:
|
||||
{ dg-final { scan-sarif-file "\"extensions\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"name\": \"diagnostic_plugin_test_paths\"" } }
|
||||
{ dg-final { scan-sarif-file "\"fullName\": \"" } }
|
||||
|
||||
{ dg-final { scan-sarif-file "\"results\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"level\": \"error\"" } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \"passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter\"" } }
|
||||
|
||||
We expect a path for the diagnostic:
|
||||
{ dg-final { scan-sarif-file "\"codeFlows\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"threadFlows\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"locations\": \\\[" } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \"when 'PyList_New' fails, returning NULL\"" } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \"when 'i < count'\"" } }
|
||||
{ dg-final { scan-sarif-file "\"text\": \"when calling 'PyList_Append', passing NULL from \\(1\\) as argument 1\"" } }
|
||||
|
||||
*/
|
|
@ -102,6 +102,7 @@ set plugin_test_list [list \
|
|||
diagnostic-test-paths-2.c \
|
||||
diagnostic-test-paths-3.c \
|
||||
diagnostic-test-paths-4.c \
|
||||
diagnostic-test-paths-5.c \
|
||||
diagnostic-path-format-plain.c \
|
||||
diagnostic-path-format-none.c \
|
||||
diagnostic-path-format-separate-events.c \
|
||||
|
|
|
@ -25,6 +25,7 @@ load_lib scanltranstree.exp
|
|||
load_lib scanipa.exp
|
||||
load_lib scanwpaipa.exp
|
||||
load_lib scanlang.exp
|
||||
load_lib scansarif.exp
|
||||
load_lib timeout.exp
|
||||
load_lib timeout-dg.exp
|
||||
load_lib prune.exp
|
||||
|
|
42
gcc/testsuite/lib/scansarif.exp
Normal file
42
gcc/testsuite/lib/scansarif.exp
Normal file
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) 2000-2022 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GCC; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Various utilities for scanning SARIF output, used by gcc-dg.exp and
|
||||
# g++-dg.exp.
|
||||
#
|
||||
# This is largely borrowed from scanasm.exp.
|
||||
|
||||
# Look for a pattern in the .sarif file produced by the compiler. See
|
||||
# dg-scan for details.
|
||||
|
||||
proc scan-sarif-file { args } {
|
||||
set testcase [testname-for-summary]
|
||||
# The name might include a list of options; extract the file name.
|
||||
set filename [lindex $testcase 0]
|
||||
set output_file "[file tail $filename].sarif"
|
||||
dg-scan "scan-sarif-file" 1 $testcase $output_file $args
|
||||
}
|
||||
|
||||
# Check that a pattern is not present in the .sarif file. See dg-scan
|
||||
# for details.
|
||||
|
||||
proc scan-sarif-file-not { args } {
|
||||
set testcase [testname-for-summary]
|
||||
# The name might include a list of options; extract the file name.
|
||||
set filename [lindex $testcase 0]
|
||||
set output_file "[file tail $filename].sarif"
|
||||
dg-scan "scan-sarif-file-not" 0 $testcase $output_file $args
|
||||
}
|
150
gcc/tree-diagnostic-client-data-hooks.cc
Normal file
150
gcc/tree-diagnostic-client-data-hooks.cc
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* Implementation of diagnostic_client_data_hooks for the compilers
|
||||
(e.g. with knowledge of "tree" and lang_hooks).
|
||||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "version.h"
|
||||
#include "tree.h"
|
||||
#include "diagnostic.h"
|
||||
#include "tree-logical-location.h"
|
||||
#include "diagnostic-client-data-hooks.h"
|
||||
#include "langhooks.h"
|
||||
#include "plugin.h"
|
||||
|
||||
/* Concrete class for supplying a diagnostic_context with information
|
||||
about a specific plugin within the client, when the client is the
|
||||
compiler (i.e. a GCC plugin). */
|
||||
|
||||
class compiler_diagnostic_client_plugin_info
|
||||
: public diagnostic_client_plugin_info
|
||||
{
|
||||
public:
|
||||
compiler_diagnostic_client_plugin_info (const plugin_name_args *args)
|
||||
: m_args (args)
|
||||
{
|
||||
}
|
||||
|
||||
const char *get_short_name () const final override
|
||||
{
|
||||
return m_args->base_name;
|
||||
}
|
||||
|
||||
const char *get_full_name () const final override
|
||||
{
|
||||
return m_args->full_name;
|
||||
}
|
||||
|
||||
const char *get_version () const final override
|
||||
{
|
||||
return m_args->version;
|
||||
}
|
||||
|
||||
private:
|
||||
const plugin_name_args *m_args;
|
||||
};
|
||||
|
||||
/* Concrete subclass of client_version_info for use by compilers proper,
|
||||
(i.e. using lang_hooks, and with knowledge of GCC plugins). */
|
||||
|
||||
class compiler_version_info : public client_version_info
|
||||
{
|
||||
public:
|
||||
const char *get_tool_name () const final override
|
||||
{
|
||||
return lang_hooks.name;
|
||||
}
|
||||
|
||||
/* Compare with toplev.cc: print_version.
|
||||
TARGET_NAME is passed in by the Makefile. */
|
||||
char *
|
||||
maybe_make_full_name () const final override
|
||||
{
|
||||
return xasprintf ("%s %sversion %s (%s)",
|
||||
get_tool_name (), pkgversion_string, version_string,
|
||||
TARGET_NAME);
|
||||
}
|
||||
|
||||
const char *get_version_string () const final override
|
||||
{
|
||||
return version_string;
|
||||
}
|
||||
|
||||
char *maybe_make_version_url () const final override
|
||||
{
|
||||
return xasprintf ("https://gcc.gnu.org/gcc-%i/", GCC_major_version);
|
||||
}
|
||||
|
||||
void for_each_plugin (plugin_visitor &visitor) const final override
|
||||
{
|
||||
::for_each_plugin (on_plugin_cb, &visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
static void
|
||||
on_plugin_cb (const plugin_name_args *args,
|
||||
void *user_data)
|
||||
{
|
||||
compiler_diagnostic_client_plugin_info cpi (args);
|
||||
client_version_info::plugin_visitor *visitor
|
||||
= (client_version_info::plugin_visitor *)user_data;
|
||||
visitor->on_plugin (cpi);
|
||||
}
|
||||
};
|
||||
|
||||
/* Subclass of diagnostic_client_data_hooks for use by compilers proper
|
||||
i.e. with knowledge of "tree", access to langhooks, etc. */
|
||||
|
||||
class compiler_data_hooks : public diagnostic_client_data_hooks
|
||||
{
|
||||
public:
|
||||
const client_version_info *get_any_version_info () const final override
|
||||
{
|
||||
return &m_version_info;
|
||||
}
|
||||
|
||||
const logical_location *get_current_logical_location () const final override
|
||||
{
|
||||
if (current_function_decl)
|
||||
return &m_current_fndecl_logical_loc;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
maybe_get_sarif_source_language (const char *filename) const final override
|
||||
{
|
||||
return lang_hooks.get_sarif_source_language (filename);
|
||||
}
|
||||
|
||||
private:
|
||||
compiler_version_info m_version_info;
|
||||
current_fndecl_logical_location m_current_fndecl_logical_loc;
|
||||
};
|
||||
|
||||
/* Create a compiler_data_hooks (so that the class can be local
|
||||
to this file). */
|
||||
|
||||
diagnostic_client_data_hooks *
|
||||
make_compiler_data_hooks ()
|
||||
{
|
||||
return new compiler_data_hooks ();
|
||||
}
|
|
@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tree-pretty-print.h"
|
||||
#include "gimple-pretty-print.h"
|
||||
#include "tree-diagnostic.h"
|
||||
#include "diagnostic-client-data-hooks.h"
|
||||
#include "langhooks.h"
|
||||
#include "intl.h"
|
||||
|
||||
|
@ -373,4 +374,5 @@ tree_diagnostics_defaults (diagnostic_context *context)
|
|||
context->print_path = default_tree_diagnostic_path_printer;
|
||||
context->make_json_for_path = default_tree_make_json_for_path;
|
||||
context->set_locations_cb = set_inlining_locations;
|
||||
context->m_client_data_hooks = make_compiler_data_hooks ();
|
||||
}
|
||||
|
|
148
gcc/tree-logical-location.cc
Normal file
148
gcc/tree-logical-location.cc
Normal file
|
@ -0,0 +1,148 @@
|
|||
/* Subclasses of logical_location with knowledge of "tree".
|
||||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree.h"
|
||||
#include "pretty-print.h"
|
||||
#include "tree-logical-location.h"
|
||||
#include "langhooks.h"
|
||||
|
||||
/* class compiler_logical_location : public logical_location. */
|
||||
|
||||
/* Get a string for DECL suitable for use by the SARIF logicalLocation
|
||||
"name" property (SARIF v2.1.0 section 3.33.4). */
|
||||
|
||||
const char *
|
||||
compiler_logical_location::get_short_name_for_tree (tree decl)
|
||||
{
|
||||
gcc_assert (decl);
|
||||
return identifier_to_locale (lang_hooks.decl_printable_name (decl, 0));
|
||||
}
|
||||
|
||||
/* Get a string for DECL suitable for use by the SARIF logicalLocation
|
||||
"fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5). */
|
||||
|
||||
const char *
|
||||
compiler_logical_location::get_name_with_scope_for_tree (tree decl)
|
||||
{
|
||||
gcc_assert (decl);
|
||||
return identifier_to_locale (lang_hooks.decl_printable_name (decl, 1));
|
||||
}
|
||||
|
||||
/* Get a string for DECL suitable for use by the SARIF logicalLocation
|
||||
"decoratedName" property (SARIF v2.1.0 section 3.33.6). */
|
||||
|
||||
const char *
|
||||
compiler_logical_location::get_internal_name_for_tree (tree decl)
|
||||
{
|
||||
gcc_assert (decl);
|
||||
if (HAS_DECL_ASSEMBLER_NAME_P (decl))
|
||||
if (tree id = DECL_ASSEMBLER_NAME (decl))
|
||||
return IDENTIFIER_POINTER (id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get what kind of SARIF logicalLocation DECL is (if any). */
|
||||
|
||||
enum logical_location_kind
|
||||
compiler_logical_location::get_kind_for_tree (tree decl)
|
||||
{
|
||||
if (!decl)
|
||||
return LOGICAL_LOCATION_KIND_UNKNOWN;
|
||||
|
||||
switch (TREE_CODE (decl))
|
||||
{
|
||||
default:
|
||||
return LOGICAL_LOCATION_KIND_UNKNOWN;
|
||||
case FUNCTION_DECL:
|
||||
return LOGICAL_LOCATION_KIND_FUNCTION;
|
||||
case PARM_DECL:
|
||||
return LOGICAL_LOCATION_KIND_PARAMETER;
|
||||
case VAR_DECL:
|
||||
return LOGICAL_LOCATION_KIND_VARIABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* class tree_logical_location : public compiler_logical_location. */
|
||||
|
||||
/* Implementation of the logical_location vfuncs, using m_decl. */
|
||||
|
||||
const char *
|
||||
tree_logical_location::get_short_name () const
|
||||
{
|
||||
gcc_assert (m_decl);
|
||||
return get_short_name_for_tree (m_decl);
|
||||
}
|
||||
|
||||
const char *
|
||||
tree_logical_location::get_name_with_scope () const
|
||||
{
|
||||
gcc_assert (m_decl);
|
||||
return get_name_with_scope_for_tree (m_decl);
|
||||
}
|
||||
|
||||
const char *
|
||||
tree_logical_location::get_internal_name () const
|
||||
{
|
||||
gcc_assert (m_decl);
|
||||
return get_internal_name_for_tree (m_decl);
|
||||
}
|
||||
|
||||
enum logical_location_kind
|
||||
tree_logical_location::get_kind () const
|
||||
{
|
||||
gcc_assert (m_decl);
|
||||
return get_kind_for_tree (m_decl);
|
||||
}
|
||||
|
||||
/* class current_fndecl_logical_location : public compiler_logical_location. */
|
||||
|
||||
/* Implementation of the logical_location vfuncs, using
|
||||
current_function_decl. */
|
||||
|
||||
const char *
|
||||
current_fndecl_logical_location::get_short_name () const
|
||||
{
|
||||
gcc_assert (current_function_decl);
|
||||
return get_short_name_for_tree (current_function_decl);
|
||||
}
|
||||
|
||||
const char *
|
||||
current_fndecl_logical_location::get_name_with_scope () const
|
||||
{
|
||||
gcc_assert (current_function_decl);
|
||||
return get_name_with_scope_for_tree (current_function_decl);
|
||||
}
|
||||
|
||||
const char *
|
||||
current_fndecl_logical_location::get_internal_name () const
|
||||
{
|
||||
gcc_assert (current_function_decl);
|
||||
return get_internal_name_for_tree (current_function_decl);
|
||||
}
|
||||
|
||||
enum logical_location_kind
|
||||
current_fndecl_logical_location::get_kind () const
|
||||
{
|
||||
gcc_assert (current_function_decl);
|
||||
return get_kind_for_tree (current_function_decl);
|
||||
}
|
67
gcc/tree-logical-location.h
Normal file
67
gcc/tree-logical-location.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* Subclasses of logical_location with knowledge of "tree".
|
||||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_TREE_LOGICAL_LOCATION_H
|
||||
#define GCC_TREE_LOGICAL_LOCATION_H
|
||||
|
||||
#include "logical-location.h"
|
||||
|
||||
/* Abstract subclass of logical_location, with knowledge of "tree", but
|
||||
for no specific tree. */
|
||||
|
||||
class compiler_logical_location : public logical_location
|
||||
{
|
||||
protected:
|
||||
static const char *get_short_name_for_tree (tree);
|
||||
static const char *get_name_with_scope_for_tree (tree);
|
||||
static const char *get_internal_name_for_tree (tree);
|
||||
static enum logical_location_kind get_kind_for_tree (tree);
|
||||
};
|
||||
|
||||
/* Concrete subclass of logical_location, with reference to a specific
|
||||
tree. */
|
||||
|
||||
class tree_logical_location : public compiler_logical_location
|
||||
{
|
||||
public:
|
||||
tree_logical_location (tree decl) : m_decl (decl) {}
|
||||
|
||||
const char *get_short_name () const final override;
|
||||
const char *get_name_with_scope () const final override;
|
||||
const char *get_internal_name () const final override;
|
||||
enum logical_location_kind get_kind () const final override;
|
||||
|
||||
private:
|
||||
tree m_decl;
|
||||
};
|
||||
|
||||
/* Concrete subclass of logical_location, with reference to
|
||||
current_function_decl. */
|
||||
|
||||
class current_fndecl_logical_location : public compiler_logical_location
|
||||
{
|
||||
public:
|
||||
const char *get_short_name () const final override;
|
||||
const char *get_name_with_scope () const final override;
|
||||
const char *get_internal_name () const final override;
|
||||
enum logical_location_kind get_kind () const final override;
|
||||
};
|
||||
|
||||
#endif /* GCC_TREE_LOGICAL_LOCATION_H. */
|
|
@ -36,6 +36,7 @@ load_gcc_lib scanasm.exp
|
|||
load_gcc_lib scandump.exp
|
||||
load_gcc_lib scanlang.exp
|
||||
load_gcc_lib scanrtl.exp
|
||||
load_gcc_lib scansarif.exp
|
||||
load_gcc_lib scantree.exp
|
||||
load_gcc_lib scanltranstree.exp
|
||||
load_gcc_lib scanipa.exp
|
||||
|
|
|
@ -28,6 +28,7 @@ load_gcc_lib scanasm.exp
|
|||
load_gcc_lib scandump.exp
|
||||
load_gcc_lib scanlang.exp
|
||||
load_gcc_lib scanrtl.exp
|
||||
load_gcc_lib scansarif.exp
|
||||
load_gcc_lib scantree.exp
|
||||
load_gcc_lib scanltranstree.exp
|
||||
load_gcc_lib scanoffload.exp
|
||||
|
|
|
@ -42,6 +42,7 @@ load_gcc_lib scanasm.exp
|
|||
load_gcc_lib scandump.exp
|
||||
load_gcc_lib scanlang.exp
|
||||
load_gcc_lib scanrtl.exp
|
||||
load_gcc_lib scansarif.exp
|
||||
load_gcc_lib scantree.exp
|
||||
load_gcc_lib scanltranstree.exp
|
||||
load_gcc_lib scanipa.exp
|
||||
|
|
|
@ -23,6 +23,7 @@ load_gcc_lib file-format.exp
|
|||
load_gcc_lib scanasm.exp
|
||||
load_gcc_lib scanlang.exp
|
||||
load_gcc_lib scanrtl.exp
|
||||
load_gcc_lib scansarif.exp
|
||||
load_gcc_lib scantree.exp
|
||||
load_gcc_lib scanipa.exp
|
||||
load_gcc_lib torture-options.exp
|
||||
|
|
Loading…
Add table
Reference in a new issue