diff options
Diffstat (limited to 'gcc/diagnostics')
-rw-r--r-- | gcc/diagnostics/output-spec.cc | 654 | ||||
-rw-r--r-- | gcc/diagnostics/output-spec.h | 24 |
2 files changed, 354 insertions, 324 deletions
diff --git a/gcc/diagnostics/output-spec.cc b/gcc/diagnostics/output-spec.cc index 8ec638a..28ea044f 100644 --- a/gcc/diagnostics/output-spec.cc +++ b/gcc/diagnostics/output-spec.cc @@ -42,13 +42,24 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/output-spec.h" /* A namespace for handling the DSL of the arguments of - -fdiagnostics-add-output= and -fdiagnostics-set-output=. */ + -fdiagnostics-add-output= and -fdiagnostics-set-output= + which look like: + SCHEME[:KEY=VALUE(,KEY=VALUE)*] + We call this an output spec. */ namespace diagnostics { namespace output_spec { +class scheme_handler; + /* Decls. */ +/* A class for the result of the first stage of parsing an output spec, + where values are represented as untyped strings. + The scheme might not exist. + The keys have not been validated against the scheme. + The values have not been validated against their keys. */ + struct scheme_name_and_params { std::string m_scheme_name; @@ -62,94 +73,12 @@ struct scheme_name_and_params class output_factory { public: - class scheme_handler - { - public: - scheme_handler (std::string scheme_name) - : m_scheme_name (std::move (scheme_name)) - {} - virtual ~scheme_handler () {} - - const std::string &get_scheme_name () const { return m_scheme_name; } - - virtual std::unique_ptr<sink> - make_sink (const context &ctxt, - diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const = 0; - - protected: - bool - parse_bool_value (const context &ctxt, - const char *unparsed_arg, - const std::string &key, - const std::string &value, - bool &out) const - { - if (value == "yes") - { - out = true; - return true; - } - else if (value == "no") - { - out = false; - return true; - } - else - { - ctxt.report_error - ("%<%s%s%>:" - " unexpected value %qs for key %qs; expected %qs or %qs", - ctxt.get_option_name (), unparsed_arg, - value.c_str (), - key.c_str (), - "yes", "no"); - - return false; - } - } - template <typename EnumType, size_t NumValues> - bool - parse_enum_value (const context &ctxt, - const char *unparsed_arg, - const std::string &key, - const std::string &value, - const std::array<std::pair<const char *, EnumType>, NumValues> &value_names, - EnumType &out) const - { - for (auto &iter : value_names) - if (value == iter.first) - { - out = iter.second; - return true; - } - - auto_vec<const char *> known_values; - for (auto iter : value_names) - known_values.safe_push (iter.first); - pp_markup::comma_separated_quoted_strings e (known_values); - ctxt.report_error - ("%<%s%s%>:" - " unexpected value %qs for key %qs; known values: %e", - ctxt.get_option_name (), unparsed_arg, - value.c_str (), - key.c_str (), - &e); - return false; - } - - private: - const std::string m_scheme_name; - }; - output_factory (); std::unique_ptr<sink> make_sink (const context &ctxt, diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg); + const scheme_name_and_params &scheme_and_kvs); const scheme_handler *get_scheme_handler (const std::string &scheme_name); @@ -157,44 +86,158 @@ private: std::vector<std::unique_ptr<scheme_handler>> m_scheme_handlers; }; -class text_scheme_handler : public output_factory::scheme_handler +class scheme_handler { public: + scheme_handler (std::string scheme_name) + : m_scheme_name (std::move (scheme_name)) + {} + virtual ~scheme_handler () {} + + const std::string &get_scheme_name () const { return m_scheme_name; } + + virtual std::unique_ptr<sink> + make_sink (const context &ctxt, + diagnostics::context &dc, + const scheme_name_and_params &scheme_and_kvs) const = 0; + +protected: + bool + parse_bool_value (const context &ctxt, + const std::string &key, + const std::string &value, + bool &out) const + { + if (value == "yes") + { + out = true; + return true; + } + else if (value == "no") + { + out = false; + return true; + } + else + { + ctxt.report_error + ("%<%s%s%>:" + " unexpected value %qs for key %qs; expected %qs or %qs", + ctxt.get_option_name (), ctxt.get_unparsed_spec (), + value.c_str (), + key.c_str (), + "yes", "no"); + + return false; + } + } + template <typename EnumType, size_t NumValues> + bool + parse_enum_value (const context &ctxt, + const std::string &key, + const std::string &value, + const std::array<std::pair<const char *, EnumType>, NumValues> &value_names, + EnumType &out) const + { + for (auto &iter : value_names) + if (value == iter.first) + { + out = iter.second; + return true; + } + + auto_vec<const char *> known_values; + for (auto iter : value_names) + known_values.safe_push (iter.first); + pp_markup::comma_separated_quoted_strings e (known_values); + ctxt.report_error + ("%<%s%s%>:" + " unexpected value %qs for key %qs; known values: %e", + ctxt.get_option_name (), ctxt.get_unparsed_spec (), + value.c_str (), + key.c_str (), + &e); + return false; + } + +private: + const std::string m_scheme_name; +}; + +class text_scheme_handler : public scheme_handler +{ +public: + struct decoded_args + { + bool m_show_color; + bool m_show_nesting; + bool m_show_locations_in_nesting; + bool m_show_levels; + }; + text_scheme_handler () : scheme_handler ("text") {} std::unique_ptr<sink> make_sink (const context &ctxt, diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const final override; + const scheme_name_and_params &scheme_and_kvs) const final override; + + bool + decode_kv (const context &ctxt, + const std::string &key, + const std::string &value, + decoded_args &out_opts) const; }; -class sarif_scheme_handler : public output_factory::scheme_handler +class sarif_scheme_handler : public scheme_handler { public: + struct decoded_args + { + label_text m_filename; + enum sarif_serialization_kind m_serialization_kind; + sarif_generation_options m_generation_opts; + }; + sarif_scheme_handler () : scheme_handler ("sarif") {} std::unique_ptr<sink> make_sink (const context &ctxt, diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const final override; + const scheme_name_and_params &scheme_and_kvs) const final override; + + bool + decode_kv (const context &ctxt, + const std::string &key, + const std::string &value, + decoded_args &out_opts) const; private: static std::unique_ptr<sarif_serialization_format> make_sarif_serialization_object (enum sarif_serialization_kind); }; -class html_scheme_handler : public output_factory::scheme_handler +class html_scheme_handler : public scheme_handler { public: + struct decoded_args + { + label_text m_filename; + html_generation_options m_html_gen_opts; + }; + html_scheme_handler () : scheme_handler ("experimental-html") {} std::unique_ptr<sink> make_sink (const context &ctxt, diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const final override; + const scheme_name_and_params &scheme_and_kvs) const final override; + + bool + decode_kv (const context &ctxt, + const std::string &key, + const std::string &value, + decoded_args &opts_out) const; }; /* struct context. */ @@ -209,8 +252,7 @@ context::report_error (const char *gmsgid, ...) const } void -context::report_unknown_key (const char *unparsed_arg, - const std::string &key, +context::report_unknown_key (const std::string &key, const std::string &scheme_name, auto_vec<const char *> &known_keys) const { @@ -218,13 +260,12 @@ context::report_unknown_key (const char *unparsed_arg, report_error ("%<%s%s%>:" " unknown key %qs for format %qs; known keys: %e", - get_option_name (), unparsed_arg, + get_option_name (), get_unparsed_spec (), key.c_str (), scheme_name.c_str (), &e); } void -context::report_missing_key (const char *unparsed_arg, - const std::string &key, +context::report_missing_key (const std::string &key, const std::string &scheme_name, const char *metavar) const { @@ -232,7 +273,7 @@ context::report_missing_key (const char *unparsed_arg, ("%<%s%s%>:" " missing required key %qs for format %qs;" " try %<%s%s:%s=%s%>", - get_option_name (), unparsed_arg, + get_option_name (), get_unparsed_spec (), key.c_str (), scheme_name.c_str (), get_option_name (), scheme_name.c_str (), key.c_str (), metavar); } @@ -250,12 +291,13 @@ context::open_output_file (label_text &&filename) const } static std::unique_ptr<scheme_name_and_params> -parse (const context &ctxt, const char *unparsed_arg) +parse (const context &ctxt) { scheme_name_and_params result; - if (const char *const colon = strchr (unparsed_arg, ':')) + const char *const unparsed_spec = ctxt.get_unparsed_spec (); + if (const char *const colon = strchr (unparsed_spec, ':')) { - result.m_scheme_name = std::string (unparsed_arg, colon - unparsed_arg); + result.m_scheme_name = std::string (unparsed_spec, colon - unparsed_spec); /* Expect zero of more of KEY=VALUE,KEY=VALUE, etc .*/ const char *iter = colon + 1; const char *last_separator = ":"; @@ -271,7 +313,7 @@ parse (const context &ctxt, const char *unparsed_arg) " expected KEY=VALUE-style parameter for format %qs" " after %qs;" " got %qs", - ctxt.get_option_name (), unparsed_arg, + ctxt.get_option_name (), ctxt.get_unparsed_spec (), result.m_scheme_name.c_str (), last_separator, iter); @@ -295,23 +337,22 @@ parse (const context &ctxt, const char *unparsed_arg) } } else - result.m_scheme_name = unparsed_arg; + result.m_scheme_name = unparsed_spec; return std::make_unique<scheme_name_and_params> (std::move (result)); } std::unique_ptr<sink> -context::parse_and_make_sink (const char *unparsed_arg, - diagnostics::context &dc) +context::parse_and_make_sink (diagnostics::context &dc) { - auto parsed_arg = parse (*this, unparsed_arg); + auto parsed_arg = parse (*this); if (!parsed_arg) return nullptr; output_factory factory; - return factory.make_sink (*this, dc, unparsed_arg, *parsed_arg); + return factory.make_sink (*this, dc, *parsed_arg); } -/* class output_factory::scheme_handler. */ +/* class scheme_handler. */ /* class output_factory. */ @@ -322,7 +363,7 @@ output_factory::output_factory () m_scheme_handlers.push_back (std::make_unique<html_scheme_handler> ()); } -const output_factory::scheme_handler * +const scheme_handler * output_factory::get_scheme_handler (const std::string &scheme_name) { for (auto &iter : m_scheme_handlers) @@ -334,10 +375,9 @@ output_factory::get_scheme_handler (const std::string &scheme_name) std::unique_ptr<sink> output_factory::make_sink (const context &ctxt, diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) + const scheme_name_and_params &scheme_and_kvs) { - auto scheme_handler = get_scheme_handler (parsed_arg.m_scheme_name); + auto scheme_handler = get_scheme_handler (scheme_and_kvs.m_scheme_name); if (!scheme_handler) { auto_vec<const char *> strings; @@ -346,155 +386,97 @@ output_factory::make_sink (const context &ctxt, pp_markup::comma_separated_quoted_strings e (strings); ctxt.report_error ("%<%s%s%>:" " unrecognized format %qs; known formats: %e", - ctxt.get_option_name (), unparsed_arg, - parsed_arg.m_scheme_name.c_str (), &e); + ctxt.get_option_name (), ctxt.get_unparsed_spec (), + scheme_and_kvs.m_scheme_name.c_str (), &e); return nullptr; } - return scheme_handler->make_sink (ctxt, dc, unparsed_arg, parsed_arg); + return scheme_handler->make_sink (ctxt, dc, scheme_and_kvs); } -/* class text_scheme_handler : public output_factory::scheme_handler. */ +/* class text_scheme_handler : public scheme_handler. */ std::unique_ptr<sink> text_scheme_handler::make_sink (const context &ctxt, diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const + const scheme_name_and_params &scheme_and_kvs) const { - bool show_color = pp_show_color (dc.get_reference_printer ()); - bool show_nesting = true; - bool show_locations_in_nesting = true; - bool show_levels = false; - for (auto& iter : parsed_arg.m_kvs) + decoded_args opts; + opts.m_show_color = pp_show_color (dc.get_reference_printer ()); + opts.m_show_nesting = true; + opts.m_show_locations_in_nesting = true; + opts.m_show_levels = false; + for (auto& iter : scheme_and_kvs.m_kvs) { const std::string &key = iter.first; const std::string &value = iter.second; - if (key == "color") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_color)) - return nullptr; - continue; - } - if (key == "show-nesting") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - show_nesting)) - return nullptr; - continue; - } - if (key == "show-nesting-locations") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - show_locations_in_nesting)) - return nullptr; - continue; - } - if (key == "show-nesting-levels") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_levels)) - return nullptr; - continue; - } - - /* Key not found. */ - auto_vec<const char *> known_keys; - known_keys.safe_push ("color"); - known_keys.safe_push ("show-nesting"); - known_keys.safe_push ("show-nesting-locations"); - known_keys.safe_push ("show-nesting-levels"); - ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (), - known_keys); - return nullptr; + if (!decode_kv (ctxt, key, value, opts)) + return nullptr; } auto sink = std::make_unique<diagnostics::text_sink> (dc); - sink->set_show_nesting (show_nesting); - sink->set_show_locations_in_nesting (show_locations_in_nesting); - sink->set_show_nesting_levels (show_levels); + sink->set_show_nesting (opts.m_show_nesting); + sink->set_show_locations_in_nesting (opts.m_show_locations_in_nesting); + sink->set_show_nesting_levels (opts.m_show_levels); + pp_show_color (sink->get_printer ()) = opts.m_show_color; return sink; } -/* class sarif_scheme_handler : public output_factory::scheme_handler. */ +bool +text_scheme_handler::decode_kv (const context &ctxt, + const std::string &key, + const std::string &value, + decoded_args &opts_out) const +{ + if (key == "color") + return parse_bool_value (ctxt, key, value, opts_out.m_show_color); + if (key == "show-nesting") + return parse_bool_value (ctxt, key, value, opts_out.m_show_nesting); + if (key == "show-nesting-locations") + return parse_bool_value (ctxt, key, value, + opts_out.m_show_locations_in_nesting); + if (key == "show-nesting-levels") + return parse_bool_value (ctxt, key, value, opts_out.m_show_levels); + + /* Key not found. */ + auto_vec<const char *> known_keys; + known_keys.safe_push ("color"); + known_keys.safe_push ("show-nesting"); + known_keys.safe_push ("show-nesting-locations"); + known_keys.safe_push ("show-nesting-levels"); + ctxt.report_unknown_key (key, get_scheme_name (), known_keys); + return false; +} + +/* class sarif_scheme_handler : public scheme_handler. */ std::unique_ptr<sink> -sarif_scheme_handler::make_sink (const context &ctxt, - diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const +sarif_scheme_handler:: +make_sink (const context &ctxt, + diagnostics::context &dc, + const scheme_name_and_params &scheme_and_kvs) const { - label_text filename; - enum sarif_serialization_kind serialization_kind - = sarif_serialization_kind::json; - sarif_generation_options sarif_gen_opts; - for (auto& iter : parsed_arg.m_kvs) + decoded_args opts; + opts.m_serialization_kind = sarif_serialization_kind::json; + + for (auto& iter : scheme_and_kvs.m_kvs) { const std::string &key = iter.first; const std::string &value = iter.second; - if (key == "file") - { - filename = label_text::take (xstrdup (value.c_str ())); - continue; - } - if (key == "serialization") - { - static const std::array<std::pair<const char *, enum sarif_serialization_kind>, - (size_t)sarif_serialization_kind::num_values> value_names - {{{"json", sarif_serialization_kind::json}}}; - - if (!parse_enum_value<enum sarif_serialization_kind> - (ctxt, unparsed_arg, - key, value, - value_names, - serialization_kind)) - return nullptr; - continue; - } - if (key == "version") - { - static const std::array<std::pair<const char *, enum sarif_version>, - (size_t)sarif_version::num_versions> value_names - {{{"2.1", sarif_version::v2_1_0}, - {"2.2-prerelease", sarif_version::v2_2_prerelease_2024_08_08}}}; - - if (!parse_enum_value<enum sarif_version> - (ctxt, unparsed_arg, - key, value, - value_names, - sarif_gen_opts.m_version)) - return nullptr; - continue; - } - if (key == "state-graphs") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - sarif_gen_opts.m_state_graph)) - return nullptr; - continue; - } - - /* Key not found. */ - auto_vec<const char *> known_keys; - known_keys.safe_push ("file"); - known_keys.safe_push ("serialization"); - known_keys.safe_push ("state-graphs"); - known_keys.safe_push ("version"); - ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (), - known_keys); - return nullptr; + if (!decode_kv (ctxt, key, value, opts)) + return nullptr; } output_file output_file_; - if (filename.get ()) - output_file_ = ctxt.open_output_file (std::move (filename)); + if (opts.m_filename.get ()) + output_file_ = ctxt.open_output_file (std::move (opts.m_filename)); else // Default filename { const char *basename = ctxt.get_base_filename (); if (!basename) { - ctxt.report_missing_key (unparsed_arg, - "file", + ctxt.report_missing_key ("file", get_scheme_name (), "FILENAME"); return nullptr; @@ -503,21 +485,71 @@ sarif_scheme_handler::make_sink (const context &ctxt, = open_sarif_output_file (dc, ctxt.get_affected_location_mgr (), basename, - serialization_kind); + opts.m_serialization_kind); } if (!output_file_) return nullptr; - auto serialization_obj = make_sarif_serialization_object (serialization_kind); + auto serialization_obj + = make_sarif_serialization_object (opts.m_serialization_kind); auto sink = make_sarif_sink (dc, *ctxt.get_affected_location_mgr (), std::move (serialization_obj), - sarif_gen_opts, + opts.m_generation_opts, std::move (output_file_)); + return sink; } +bool +sarif_scheme_handler::decode_kv (const context &ctxt, + const std::string &key, + const std::string &value, + decoded_args &opts_out) const +{ + if (key == "file") + { + opts_out.m_filename = label_text::take (xstrdup (value.c_str ())); + return true; + } + if (key == "serialization") + { + static const std::array<std::pair<const char *, enum sarif_serialization_kind>, + (size_t)sarif_serialization_kind::num_values> value_names + {{{"json", sarif_serialization_kind::json}}}; + return parse_enum_value<enum sarif_serialization_kind> + (ctxt, + key, value, + value_names, + opts_out.m_serialization_kind); + } + if (key == "version") + { + static const std::array<std::pair<const char *, enum sarif_version>, + (size_t)sarif_version::num_versions> value_names + {{{"2.1", sarif_version::v2_1_0}, + {"2.2-prerelease", sarif_version::v2_2_prerelease_2024_08_08}}}; + return parse_enum_value<enum sarif_version> + (ctxt, + key, value, + value_names, + opts_out.m_generation_opts.m_version); + } + if (key == "state-graphs") + return parse_bool_value (ctxt, key, value, + opts_out.m_generation_opts.m_state_graph); + + /* Key not found. */ + auto_vec<const char *> known_keys; + known_keys.safe_push ("file"); + known_keys.safe_push ("serialization"); + known_keys.safe_push ("state-graphs"); + known_keys.safe_push ("version"); + ctxt.report_unknown_key (key, get_scheme_name (), known_keys); + return false; +} + std::unique_ptr<sarif_serialization_format> sarif_scheme_handler:: make_sarif_serialization_object (enum sarif_serialization_kind kind) @@ -532,85 +564,33 @@ make_sarif_serialization_object (enum sarif_serialization_kind kind) } } -/* class html_scheme_handler : public output_factory::scheme_handler. */ +/* class html_scheme_handler : public scheme_handler. */ std::unique_ptr<sink> -html_scheme_handler::make_sink (const context &ctxt, - diagnostics::context &dc, - const char *unparsed_arg, - const scheme_name_and_params &parsed_arg) const +html_scheme_handler:: +make_sink (const context &ctxt, + diagnostics::context &dc, + const scheme_name_and_params &scheme_and_kvs) const { - label_text filename; - html_generation_options html_gen_opts; - for (auto& iter : parsed_arg.m_kvs) + decoded_args opts; + for (auto& iter : scheme_and_kvs.m_kvs) { const std::string &key = iter.first; const std::string &value = iter.second; - if (key == "css") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - html_gen_opts.m_css)) - return nullptr; - continue; - } - if (key == "file") - { - filename = label_text::take (xstrdup (value.c_str ())); - continue; - } - if (key == "javascript") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - html_gen_opts.m_javascript)) - return nullptr; - continue; - } - if (key == "show-state-diagrams") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - html_gen_opts.m_show_state_diagrams)) - return nullptr; - continue; - } - if (key == "show-state-diagrams-dot-src") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - html_gen_opts.m_show_state_diagrams_dot_src)) - return nullptr; - continue; - } - if (key == "show-state-diagrams-sarif") - { - if (!parse_bool_value (ctxt, unparsed_arg, key, value, - html_gen_opts.m_show_state_diagrams_sarif)) - return nullptr; - continue; - } - - /* Key not found. */ - auto_vec<const char *> known_keys; - known_keys.safe_push ("css"); - known_keys.safe_push ("file"); - known_keys.safe_push ("javascript"); - known_keys.safe_push ("show-state-diagrams"); - known_keys.safe_push ("show-state-diagram-dot-src"); - known_keys.safe_push ("show-state-diagram-sarif"); - ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (), - known_keys); - return nullptr; + if (!decode_kv (ctxt, key, value, opts)) + return nullptr; } output_file output_file_; - if (filename.get ()) - output_file_ = ctxt.open_output_file (std::move (filename)); + if (opts.m_filename.get ()) + output_file_ = ctxt.open_output_file (std::move (opts.m_filename)); else // Default filename { const char *basename = ctxt.get_base_filename (); if (!basename) { - ctxt.report_missing_key (unparsed_arg, - "file", + ctxt.report_missing_key ("file", get_scheme_name (), "FILENAME"); return nullptr; @@ -626,11 +606,51 @@ html_scheme_handler::make_sink (const context &ctxt, auto sink = make_html_sink (dc, *ctxt.get_affected_location_mgr (), - html_gen_opts, + opts.m_html_gen_opts, std::move (output_file_)); return sink; } +bool +html_scheme_handler::decode_kv (const context &ctxt, + const std::string &key, + const std::string &value, + decoded_args &opts_out) const +{ + if (key == "css") + return parse_bool_value (ctxt, key, value, opts_out.m_html_gen_opts.m_css); + if (key == "file") + { + opts_out.m_filename = label_text::take (xstrdup (value.c_str ())); + return true; + } + if (key == "javascript") + return parse_bool_value (ctxt, key, value, + opts_out.m_html_gen_opts.m_javascript); + if (key == "show-state-diagrams") + return parse_bool_value (ctxt, key, value, + opts_out.m_html_gen_opts.m_show_state_diagrams); + if (key == "show-state-diagrams-dot-src") + return parse_bool_value + (ctxt, key, value, + opts_out.m_html_gen_opts.m_show_state_diagrams_dot_src); + if (key == "show-state-diagrams-sarif") + return parse_bool_value + (ctxt, key, value, + opts_out.m_html_gen_opts.m_show_state_diagrams_sarif); + + /* Key not found. */ + auto_vec<const char *> known_keys; + known_keys.safe_push ("css"); + known_keys.safe_push ("file"); + known_keys.safe_push ("javascript"); + known_keys.safe_push ("show-state-diagrams"); + known_keys.safe_push ("show-state-diagram-dot-src"); + known_keys.safe_push ("show-state-diagram-sarif"); + ctxt.report_unknown_key (key, get_scheme_name (), known_keys); + return false; +} + } // namespace output_spec #if CHECKING_P @@ -668,12 +688,14 @@ struct parser_test test_spec_context (diagnostics::context &dc, line_maps *location_mgr, location_t loc, - const char *option_name) + const char *option_name, + const char *unparsed_arg) : dc_spec_context (dc, location_mgr, location_mgr, loc, - option_name) + option_name, + unparsed_arg) { } @@ -684,18 +706,18 @@ struct parser_test } }; - parser_test () + parser_test (const char *unparsed_spec) : m_dc (), - m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION="), + m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION=", unparsed_spec), m_fmt (m_dc.get_sink (0)) { pp_buffer (m_fmt.get_printer ())->m_flush_p = false; } std::unique_ptr<diagnostics::output_spec::scheme_name_and_params> - parse (const char *unparsed_arg) + parse () { - return diagnostics::output_spec::parse (m_ctxt, unparsed_arg); + return diagnostics::output_spec::parse (m_ctxt); } bool execution_failed_p () const @@ -725,8 +747,8 @@ test_output_arg_parsing () /* Minimal correct example. */ { - parser_test pt; - auto result = pt.parse ("foo"); + parser_test pt ("foo"); + auto result = pt.parse (); ASSERT_EQ (result->m_scheme_name, "foo"); ASSERT_EQ (result->m_kvs.size (), 0); ASSERT_FALSE (pt.execution_failed_p ()); @@ -734,8 +756,8 @@ test_output_arg_parsing () /* Stray trailing colon with no key/value pairs. */ { - parser_test pt; - auto result = pt.parse ("foo:"); + parser_test pt ("foo:"); + auto result = pt.parse (); ASSERT_EQ (result, nullptr); ASSERT_TRUE (pt.execution_failed_p ()); ASSERT_STREQ (pt.get_diagnostic_text (), @@ -747,8 +769,8 @@ test_output_arg_parsing () /* No key before '='. */ { - parser_test pt; - auto result = pt.parse ("foo:="); + parser_test pt ("foo:="); + auto result = pt.parse (); ASSERT_EQ (result, nullptr); ASSERT_TRUE (pt.execution_failed_p ()); ASSERT_STREQ (pt.get_diagnostic_text (), @@ -760,8 +782,8 @@ test_output_arg_parsing () /* No value for key. */ { - parser_test pt; - auto result = pt.parse ("foo:key,"); + parser_test pt ("foo:key,"); + auto result = pt.parse (); ASSERT_EQ (result, nullptr); ASSERT_TRUE (pt.execution_failed_p ()); ASSERT_STREQ (pt.get_diagnostic_text (), @@ -773,8 +795,8 @@ test_output_arg_parsing () /* Correct example, with one key/value pair. */ { - parser_test pt; - auto result = pt.parse ("foo:key=value"); + parser_test pt ("foo:key=value"); + auto result = pt.parse (); ASSERT_EQ (result->m_scheme_name, "foo"); ASSERT_EQ (result->m_kvs.size (), 1); ASSERT_EQ (result->m_kvs[0].first, "key"); @@ -784,8 +806,8 @@ test_output_arg_parsing () /* Stray trailing comma. */ { - parser_test pt; - auto result = pt.parse ("foo:key=value,"); + parser_test pt ("foo:key=value,"); + auto result = pt.parse (); ASSERT_EQ (result, nullptr); ASSERT_TRUE (pt.execution_failed_p ()); ASSERT_STREQ (pt.get_diagnostic_text (), @@ -797,8 +819,8 @@ test_output_arg_parsing () /* Correct example, with two key/value pairs. */ { - parser_test pt; - auto result = pt.parse ("foo:color=red,shape=circle"); + parser_test pt ("foo:color=red,shape=circle"); + auto result = pt.parse (); ASSERT_EQ (result->m_scheme_name, "foo"); ASSERT_EQ (result->m_kvs.size (), 2); ASSERT_EQ (result->m_kvs[0].first, "color"); diff --git a/gcc/diagnostics/output-spec.h b/gcc/diagnostics/output-spec.h index c84d237..e24002b 100644 --- a/gcc/diagnostics/output-spec.h +++ b/gcc/diagnostics/output-spec.h @@ -34,22 +34,19 @@ class context { public: std::unique_ptr<sink> - parse_and_make_sink (const char *, - diagnostics::context &dc); + parse_and_make_sink (diagnostics::context &dc); void report_error (const char *gmsgid, ...) const ATTRIBUTE_GCC_DIAG(2,3); void - report_unknown_key (const char *unparsed_arg, - const std::string &key, + report_unknown_key (const std::string &key, const std::string &scheme_name, auto_vec<const char *> &known_keys) const; void - report_missing_key (const char *unparsed_arg, - const std::string &key, + report_missing_key (const std::string &key, const std::string &scheme_name, const char *metavar) const; @@ -59,6 +56,9 @@ class context const char * get_option_name () const { return m_option_name; } + const char * + get_unparsed_spec () const { return m_unparsed_spec; } + line_maps * get_affected_location_mgr () const { return m_affected_location_mgr; } @@ -72,13 +72,20 @@ class context protected: context (const char *option_name, + const char *unparsed_spec, line_maps *affected_location_mgr) : m_option_name (option_name), + m_unparsed_spec (unparsed_spec), m_affected_location_mgr (affected_location_mgr) { } + // e.g. "-fdiagnostics-add-output=" const char *m_option_name; + + // e.g. "scheme:foo=bar,key=value" + const char *m_unparsed_spec; + line_maps *m_affected_location_mgr; }; @@ -91,8 +98,9 @@ public: line_maps *affected_location_mgr, line_maps *control_location_mgr, location_t loc, - const char *option_name) - : context (option_name, affected_location_mgr), + const char *option_name, + const char *unparsed_spec) + : context (option_name, unparsed_spec, affected_location_mgr), m_dc (dc), m_control_location_mgr (control_location_mgr), m_loc (loc) |