Line data Source code
1 : /* Support for the DSL of -fdiagnostics-add-output= and
2 : -fdiagnostics-set-output=.
3 : Copyright (C) 2024-2026 Free Software Foundation, Inc.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_DIAGNOSTICS_OUTPUT_SPEC_H
22 : #define GCC_DIAGNOSTICS_OUTPUT_SPEC_H
23 :
24 : #include "diagnostics/sink.h"
25 : #include "diagnostics/output-file.h"
26 :
27 : namespace diagnostics {
28 : namespace output_spec {
29 :
30 : class context;
31 :
32 : /* An abstract base class for schemes, and for client-specific keys. */
33 :
34 54 : class key_handler
35 : {
36 : public:
37 : enum class result
38 : {
39 : ok,
40 : unrecognized,
41 : malformed_value
42 : };
43 :
44 : /* Attempt to decode KEY and VALUE, storing the decoded value. */
45 : virtual enum result
46 : maybe_handle_kv (const context &ctxt,
47 : const std::string &key,
48 : const std::string &value) = 0;
49 :
50 : virtual void
51 : get_keys (auto_vec<const char *> &out) const = 0;
52 :
53 : enum result
54 : parse_bool_value (const context &ctxt,
55 : const std::string &key,
56 : const std::string &value,
57 : bool &out) const;
58 :
59 : template <typename EnumType, size_t NumValues>
60 : enum result
61 : parse_enum_value (const context &ctxt,
62 : const std::string &key,
63 : const std::string &value,
64 : const std::array<std::pair<const char *, EnumType>,
65 : NumValues> &value_names,
66 : EnumType &out) const;
67 : };
68 :
69 : /* Abstract subclass for handling particular schemes and their keys. */
70 :
71 : class scheme_handler : public key_handler
72 : {
73 : public:
74 162 : scheme_handler (std::string scheme_name)
75 162 : : m_scheme_name (std::move (scheme_name))
76 : {}
77 : virtual ~scheme_handler () {}
78 :
79 106 : const std::string &get_scheme_name () const { return m_scheme_name; }
80 :
81 : virtual std::unique_ptr<sink>
82 : make_sink (const context &ctxt,
83 : diagnostics::context &dc) = 0;
84 :
85 : private:
86 : const std::string m_scheme_name;
87 : };
88 :
89 : /* An abstract base class for handling the DSL of -fdiagnostics-add-output=
90 : and -fdiagnostics-set-output=. */
91 :
92 : class context
93 : {
94 : public:
95 : std::unique_ptr<sink>
96 : parse_and_make_sink (diagnostics::context &dc);
97 :
98 : void
99 : report_error (const char *gmsgid, ...) const
100 : ATTRIBUTE_GCC_DIAG(2,3);
101 :
102 : void
103 : report_unknown_key (const std::string &key,
104 : const scheme_handler &scheme) const;
105 :
106 : void
107 : report_missing_key (const std::string &key,
108 : const std::string &scheme_name,
109 : const char *metavar) const;
110 :
111 : output_file
112 : open_output_file (label_text &&filename) const;
113 :
114 : const char *
115 16 : get_option_name () const { return m_option_name; }
116 :
117 : const char *
118 98 : get_unparsed_spec () const { return m_unparsed_spec; }
119 :
120 : line_maps *
121 74 : get_affected_location_mgr () const { return m_affected_location_mgr; }
122 :
123 82 : virtual ~context () {}
124 :
125 : virtual void
126 : report_error_va (const char *gmsgid, va_list *ap) const = 0;
127 :
128 : virtual const char *
129 : get_base_filename () const = 0;
130 :
131 : bool
132 : handle_kv (const std::string &key,
133 : const std::string &value,
134 : scheme_handler &scheme) const;
135 :
136 : protected:
137 82 : context (const char *option_name,
138 : const char *unparsed_spec,
139 : key_handler *client_keys,
140 : line_maps *affected_location_mgr)
141 82 : : m_option_name (option_name),
142 82 : m_unparsed_spec (unparsed_spec),
143 82 : m_client_keys (client_keys),
144 82 : m_affected_location_mgr (affected_location_mgr)
145 : {
146 : }
147 :
148 : // e.g. "-fdiagnostics-add-output="
149 : const char *m_option_name;
150 :
151 : // e.g. "scheme:foo=bar,key=value"
152 : const char *m_unparsed_spec;
153 :
154 : // Optional borrowed ptr to client-specific keys
155 : key_handler *m_client_keys;
156 :
157 : line_maps *m_affected_location_mgr;
158 : };
159 :
160 : /* A subclass that implements reporting errors via a diagnostics::context. */
161 :
162 82 : struct dc_spec_context : public output_spec::context
163 : {
164 : public:
165 82 : dc_spec_context (const char *option_name,
166 : const char *unparsed_spec,
167 : key_handler *client_keys,
168 : line_maps *affected_location_mgr,
169 : diagnostics::context &dc,
170 : line_maps *control_location_mgr,
171 : location_t loc)
172 82 : : context (option_name,
173 : unparsed_spec,
174 : client_keys,
175 : affected_location_mgr),
176 82 : m_dc (dc),
177 82 : m_control_location_mgr (control_location_mgr),
178 82 : m_loc (loc)
179 : {}
180 :
181 16 : void report_error_va (const char *gmsgid, va_list *ap) const final override
182 : ATTRIBUTE_GCC_DIAG(2, 0)
183 : {
184 16 : m_dc.begin_group ();
185 16 : rich_location richloc (m_control_location_mgr, m_loc);
186 16 : m_dc.diagnostic_impl (&richloc, nullptr, -1, gmsgid, ap, kind::error);
187 16 : m_dc.end_group ();
188 16 : }
189 :
190 : diagnostics::context &m_dc;
191 : line_maps *m_control_location_mgr;
192 : location_t m_loc;
193 : };
194 :
195 : } // namespace output_spec
196 : } // namespace diagnostics
197 :
198 : #endif // #ifndef GCC_DIAGNOSTICS_OUTPUT_SPEC_H
|