1 // rust-diagnostics.cc -- GCC implementation of rust diagnostics interface.
2 // Copyright (C) 2016-2023 Free Software Foundation, Inc.
3 // Contributed by Than McIntosh, Google.
5 // This file is part of GCC.
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
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
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/>.
21 #include "rust-system.h"
22 #include "rust-diagnostics.h"
25 #include "diagnostic-metadata.h"
30 return std::string (xstrerror (errno
));
33 // Rewrite a format string to expand any extensions not
34 // supported by sprintf(). See comments in rust-diagnostics.h
35 // for list of supported format specifiers.
38 expand_format (const char *fmt
)
41 for (const char *c
= fmt
; *c
; ++c
)
52 // malformed format string
60 ss
<< mformat_value ();
64 ss
<< rust_open_quote ();
68 ss
<< rust_close_quote ();
72 ss
<< rust_open_quote ();
76 ss
<< mformat_value ();
82 ss
<< rust_close_quote ();
93 // Expand message format specifiers, using a combination of
94 // expand_format above to handle extensions (ex: %m, %q) and vasprintf()
95 // to handle regular printf-style formatting. A pragma is being used here to
96 // suppress this warning:
98 // warning: function ‘std::__cxx11::string expand_message(const char*,
99 // __va_list_tag*)’ might be a candidate for ‘gnu_printf’ format attribute
100 // [-Wsuggest-attribute=format]
102 // What appears to be happening here is that the checker is deciding that
103 // because of the call to vasprintf() (which has attribute gnu_printf), the
104 // calling function must need to have attribute gnu_printf as well, even
105 // though there is already an attribute declaration for it.
108 expand_message (const char *fmt
, va_list ap
) RUST_ATTRIBUTE_GCC_DIAG (1, 0);
110 #pragma GCC diagnostic push
111 #pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
114 expand_message (const char *fmt
, va_list ap
)
117 std::string expanded_fmt
= expand_format (fmt
);
118 int nwr
= vasprintf (&mbuf
, expanded_fmt
.c_str (), ap
);
121 // memory allocation failed
122 rust_be_error_at (Linemap::unknown_location (),
123 "memory allocation failed in vasprintf");
126 std::string rval
= std::string (mbuf
);
131 #pragma GCC diagnostic pop
133 static const char *cached_open_quote
= NULL
;
134 static const char *cached_close_quote
= NULL
;
137 rust_be_get_quotechars (const char **open_qu
, const char **close_qu
)
139 *open_qu
= open_quote
;
140 *close_qu
= close_quote
;
146 if (cached_open_quote
== NULL
)
147 rust_be_get_quotechars (&cached_open_quote
, &cached_close_quote
);
148 return cached_open_quote
;
154 if (cached_close_quote
== NULL
)
155 rust_be_get_quotechars (&cached_open_quote
, &cached_close_quote
);
156 return cached_close_quote
;
160 rust_be_internal_error_at (const Location location
, const std::string
&errmsg
)
162 std::string loc_str
= Linemap::location_to_string (location
);
163 if (loc_str
.empty ())
164 internal_error ("%s", errmsg
.c_str ());
166 internal_error ("at %s, %s", loc_str
.c_str (), errmsg
.c_str ());
170 rust_internal_error_at (const Location location
, const char *fmt
, ...)
175 rust_be_internal_error_at (location
, expand_message (fmt
, ap
));
180 rust_be_error_at (const Location location
, const std::string
&errmsg
)
182 location_t gcc_loc
= location
.gcc_location ();
183 error_at (gcc_loc
, "%s", errmsg
.c_str ());
187 rust_error_at (const Location location
, const char *fmt
, ...)
192 rust_be_error_at (location
, expand_message (fmt
, ap
));
196 class rust_error_code_rule
: public diagnostic_metadata::rule
199 rust_error_code_rule (const ErrorCode code
) : m_code (code
) {}
201 char *make_description () const final override
203 return xstrdup (m_code
.m_str
);
206 char *make_url () const final override
208 return concat ("https://doc.rust-lang.org/error-index.html#", m_code
.m_str
,
213 const ErrorCode m_code
;
217 rust_be_error_at (const RichLocation
&location
, const ErrorCode code
,
218 const std::string
&errmsg
)
220 /* TODO: 'error_at' would like a non-'const' 'rich_location *'. */
221 rich_location
&gcc_loc
= const_cast<rich_location
&> (location
.get ());
222 diagnostic_metadata m
;
223 rust_error_code_rule
rule (code
);
225 error_meta (&gcc_loc
, m
, "%s", errmsg
.c_str ());
229 rust_error_at (const RichLocation
&location
, const ErrorCode code
,
230 const char *fmt
, ...)
235 rust_be_error_at (location
, code
, expand_message (fmt
, ap
));
240 rust_be_warning_at (const Location location
, int opt
,
241 const std::string
&warningmsg
)
243 location_t gcc_loc
= location
.gcc_location ();
244 warning_at (gcc_loc
, opt
, "%s", warningmsg
.c_str ());
248 rust_warning_at (const Location location
, int opt
, const char *fmt
, ...)
253 rust_be_warning_at (location
, opt
, expand_message (fmt
, ap
));
258 rust_be_fatal_error (const Location location
, const std::string
&fatalmsg
)
260 location_t gcc_loc
= location
.gcc_location ();
261 fatal_error (gcc_loc
, "%s", fatalmsg
.c_str ());
265 rust_fatal_error (const Location location
, const char *fmt
, ...)
270 rust_be_fatal_error (location
, expand_message (fmt
, ap
));
275 rust_be_inform (const Location location
, const std::string
&infomsg
)
277 location_t gcc_loc
= location
.gcc_location ();
278 inform (gcc_loc
, "%s", infomsg
.c_str ());
282 rust_inform (const Location location
, const char *fmt
, ...)
287 rust_be_inform (location
, expand_message (fmt
, ap
));
293 rust_be_error_at (const RichLocation
&location
, const std::string
&errmsg
)
295 /* TODO: 'error_at' would like a non-'const' 'rich_location *'. */
296 rich_location
&gcc_loc
= const_cast<rich_location
&> (location
.get ());
297 error_at (&gcc_loc
, "%s", errmsg
.c_str ());
301 rust_error_at (const RichLocation
&location
, const char *fmt
, ...)
306 rust_be_error_at (location
, expand_message (fmt
, ap
));
311 rust_be_debug_p (void)
313 return !!flag_rust_debug
;
317 rust_debug_loc (const Location location
, const char *fmt
, ...)
319 if (!rust_be_debug_p ())
326 int nwr
= vasprintf (&mbuf
, fmt
, ap
);
330 rust_be_error_at (Linemap::unknown_location (),
331 "memory allocation failed in vasprintf");
334 std::string rval
= std::string (mbuf
);
336 rust_be_inform (location
, rval
);
342 * This function takes ownership of `args` and calls `va_end` on it
345 va_constructor (Error::Kind kind
, Location locus
, const char *fmt
, va_list args
)
346 RUST_ATTRIBUTE_GCC_DIAG (3, 0);
349 va_constructor (Error::Kind kind
, Location locus
, const char *fmt
, va_list args
)
351 std::string message
= expand_message (fmt
, args
);
352 message
.shrink_to_fit ();
355 return Error (kind
, locus
, message
);
358 Error::Error (const Location location
, const char *fmt
, ...)
359 : kind (Kind::Err
), locus (location
)
364 *this = va_constructor (Kind::Err
, location
, fmt
, ap
);
368 Error::Hint (const Location location
, const char *fmt
, ...)
373 return va_constructor (Kind::Hint
, location
, fmt
, ap
);
377 Error::Fatal (const Location location
, const char *fmt
, ...)
382 return va_constructor (Kind::FatalErr
, location
, fmt
, ap
);