Extend fold_vec_perm to handle VLA vector_cst.
[official-gcc.git] / gcc / rust / rust-diagnostics.cc
blob4e5c2ececd46b01ebd2a57879a376d115c98f320
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
10 // version.
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.
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"
24 static std::string
25 mformat_value ()
27 return std::string (xstrerror (errno));
30 // Rewrite a format string to expand any extensions not
31 // supported by sprintf(). See comments in rust-diagnostics.h
32 // for list of supported format specifiers.
34 static std::string
35 expand_format (const char *fmt)
37 std::stringstream ss;
38 for (const char *c = fmt; *c; ++c)
40 if (*c != '%')
42 ss << *c;
43 continue;
45 c++;
46 switch (*c)
48 case '\0': {
49 // malformed format string
50 rust_unreachable ();
52 case '%': {
53 ss << "%";
54 break;
56 case 'm': {
57 ss << mformat_value ();
58 break;
60 case '<': {
61 ss << rust_open_quote ();
62 break;
64 case '>': {
65 ss << rust_close_quote ();
66 break;
68 case 'q': {
69 ss << rust_open_quote ();
70 c++;
71 if (*c == 'm')
73 ss << mformat_value ();
75 else
77 ss << "%" << *c;
79 ss << rust_close_quote ();
80 break;
82 default: {
83 ss << "%" << *c;
87 return ss.str ();
90 // Expand message format specifiers, using a combination of
91 // expand_format above to handle extensions (ex: %m, %q) and vasprintf()
92 // to handle regular printf-style formatting. A pragma is being used here to
93 // suppress this warning:
95 // warning: function ‘std::__cxx11::string expand_message(const char*,
96 // __va_list_tag*)’ might be a candidate for ‘gnu_printf’ format attribute
97 // [-Wsuggest-attribute=format]
99 // What appears to be happening here is that the checker is deciding that
100 // because of the call to vasprintf() (which has attribute gnu_printf), the
101 // calling function must need to have attribute gnu_printf as well, even
102 // though there is already an attribute declaration for it.
104 static std::string
105 expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0);
107 #pragma GCC diagnostic push
108 #pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
110 static std::string
111 expand_message (const char *fmt, va_list ap)
113 char *mbuf = 0;
114 std::string expanded_fmt = expand_format (fmt);
115 int nwr = vasprintf (&mbuf, expanded_fmt.c_str (), ap);
116 if (nwr == -1)
118 // memory allocation failed
119 rust_be_error_at (Linemap::unknown_location (),
120 "memory allocation failed in vasprintf");
121 rust_assert (0);
123 std::string rval = std::string (mbuf);
124 free (mbuf);
125 return rval;
128 #pragma GCC diagnostic pop
130 static const char *cached_open_quote = NULL;
131 static const char *cached_close_quote = NULL;
133 const char *
134 rust_open_quote ()
136 if (cached_open_quote == NULL)
137 rust_be_get_quotechars (&cached_open_quote, &cached_close_quote);
138 return cached_open_quote;
141 const char *
142 rust_close_quote ()
144 if (cached_close_quote == NULL)
145 rust_be_get_quotechars (&cached_open_quote, &cached_close_quote);
146 return cached_close_quote;
149 void
150 rust_internal_error_at (const Location location, const char *fmt, ...)
152 va_list ap;
154 va_start (ap, fmt);
155 rust_be_internal_error_at (location, expand_message (fmt, ap));
156 va_end (ap);
159 void
160 rust_error_at (const Location location, const char *fmt, ...)
162 va_list ap;
164 va_start (ap, fmt);
165 rust_be_error_at (location, expand_message (fmt, ap));
166 va_end (ap);
169 void
170 rust_warning_at (const Location location, int opt, const char *fmt, ...)
172 va_list ap;
174 va_start (ap, fmt);
175 rust_be_warning_at (location, opt, expand_message (fmt, ap));
176 va_end (ap);
179 void
180 rust_fatal_error (const Location location, const char *fmt, ...)
182 va_list ap;
184 va_start (ap, fmt);
185 rust_be_fatal_error (location, expand_message (fmt, ap));
186 va_end (ap);
189 void
190 rust_inform (const Location location, const char *fmt, ...)
192 va_list ap;
194 va_start (ap, fmt);
195 rust_be_inform (location, expand_message (fmt, ap));
196 va_end (ap);
199 // Rich Locations
200 void
201 rust_error_at (const RichLocation &location, const char *fmt, ...)
203 va_list ap;
205 va_start (ap, fmt);
206 rust_be_error_at (location, expand_message (fmt, ap));
207 va_end (ap);
210 void
211 rust_debug_loc (const Location location, const char *fmt, ...)
213 if (!rust_be_debug_p ())
214 return;
216 va_list ap;
218 va_start (ap, fmt);
219 char *mbuf = NULL;
220 int nwr = vasprintf (&mbuf, fmt, ap);
221 va_end (ap);
222 if (nwr == -1)
224 rust_be_error_at (Linemap::unknown_location (),
225 "memory allocation failed in vasprintf");
226 rust_assert (0);
228 std::string rval = std::string (mbuf);
229 free (mbuf);
230 rust_be_inform (location, rval);
233 namespace Rust {
236 * This function takes ownership of `args` and calls `va_end` on it
238 static Error
239 va_constructor (Error::Kind kind, Location locus, const char *fmt, va_list args)
240 RUST_ATTRIBUTE_GCC_DIAG (3, 0);
242 static Error
243 va_constructor (Error::Kind kind, Location locus, const char *fmt, va_list args)
245 std::string message = expand_message (fmt, args);
246 message.shrink_to_fit ();
247 va_end (args);
249 return Error (kind, locus, message);
252 Error::Error (const Location location, const char *fmt, ...)
253 : kind (Kind::Err), locus (location)
255 va_list ap;
256 va_start (ap, fmt);
258 *this = va_constructor (Kind::Err, location, fmt, ap);
261 Error
262 Error::Hint (const Location location, const char *fmt, ...)
264 va_list ap;
265 va_start (ap, fmt);
267 return va_constructor (Kind::Hint, location, fmt, ap);
270 Error
271 Error::Fatal (const Location location, const char *fmt, ...)
273 va_list ap;
274 va_start (ap, fmt);
276 return va_constructor (Kind::FatalErr, location, fmt, ap);
279 } // namespace Rust