1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
2
3 // This file is part of GCC.
4
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
8 // version.
9
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
18
19 // rust-diagnostics.h -- interface to diagnostic reporting -*- C++ -*-
20
21 #ifndef RUST_DIAGNOSTICS_H
22 #define RUST_DIAGNOSTICS_H
23
24 #include "rust-linemap.h"
25
26 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
27 #define RUST_ATTRIBUTE_GCC_DIAG(m, n) \
28 __attribute__ ((__format__ (__gcc_tdiag__, m, n))) \
29 __attribute__ ((__nonnull__ (m)))
30 #else
31 #define RUST_ATTRIBUTE_GCC_DIAG(m, n)
32 #endif
33
34 // These declarations define the interface through which the frontend
35 // reports errors and warnings. These functions accept printf-like
36 // format specifiers (e.g. %d, %f, %s, etc), with the following additional
37 // extensions:
38 //
39 // 1. 'q' qualifier may be applied to a specifier to add quoting, e.g.
40 // %qd produces a quoted decimal output, %qs a quoted string output.
41 // [This extension is supported only with single-character format
42 // specifiers].
43 //
44 // 2. %m specifier outputs value of "strerror(errno)" at time of call.
45 //
46 // 3. %< outputs an opening quote, %> a closing quote.
47 //
48 // All other format specifiers are as defined by 'sprintf'. The final resulting
49 // message is then sent to the back end via rust_be_error_at/rust_be_warning_at.
50
51 // clang-format off
52 // simple location
53 extern void
54 rust_internal_error_at (const Location, const char *fmt, ...)
55 RUST_ATTRIBUTE_GCC_DIAG (2, 3)
56 RUST_ATTRIBUTE_NORETURN;
57 extern void
58 rust_error_at (const Location, const char *fmt, ...)
59 RUST_ATTRIBUTE_GCC_DIAG (2, 3);
60 extern void
61 rust_warning_at (const Location, int opt, const char *fmt, ...)
62 RUST_ATTRIBUTE_GCC_DIAG (3, 4);
63 extern void
64 rust_fatal_error (const Location, const char *fmt, ...)
65 RUST_ATTRIBUTE_GCC_DIAG (2, 3)
66 RUST_ATTRIBUTE_NORETURN;
67 extern void
68 rust_inform (const Location, const char *fmt, ...)
69 RUST_ATTRIBUTE_GCC_DIAG (2, 3);
70
71 // rich locations
72 extern void
73 rust_error_at (const RichLocation &, const char *fmt, ...)
74 RUST_ATTRIBUTE_GCC_DIAG (2, 3);
75 // clang-format on
76
77 // These interfaces provide a way for the front end to ask for
78 // the open/close quote characters it should use when formatting
79 // diagnostics (warnings, errors).
80 extern const char *
81 rust_open_quote ();
82 extern const char *
83 rust_close_quote ();
84
85 // These interfaces are used by utilities above to pass warnings and
86 // errors (once format specifiers have been expanded) to the back end,
87 // and to determine quoting style. Avoid calling these routines directly;
88 // instead use the equivalent routines above. The back end is required to
89 // implement these routines.
90
91 // clang-format off
92 extern void
93 rust_be_internal_error_at (const Location, const std::string &errmsg)
94 RUST_ATTRIBUTE_NORETURN;
95 extern void
96 rust_be_error_at (const Location, const std::string &errmsg);
97 extern void
98 rust_be_error_at (const RichLocation &, const std::string &errmsg);
99 extern void
100 rust_be_warning_at (const Location, int opt, const std::string &warningmsg);
101 extern void
102 rust_be_fatal_error (const Location, const std::string &errmsg)
103 RUST_ATTRIBUTE_NORETURN;
104 extern void
105 rust_be_inform (const Location, const std::string &infomsg);
106 extern void
107 rust_be_get_quotechars (const char **open_quote, const char **close_quote);
108 extern bool
109 rust_be_debug_p (void);
110 // clang-format on
111
112 namespace Rust {
113 /* A structure used to represent an error. Useful for enabling
114 * errors to be ignored, e.g. if backtracking. */
115 struct Error
116 {
117 enum class Kind
118 {
119 Hint,
120 Err,
121 FatalErr,
122 };
123
124 Kind kind;
125 Location locus;
126 std::string message;
127 // TODO: store more stuff? e.g. node id?
128
129 Error (Kind kind, Location locus, std::string message)
130 : kind (kind), locus (locus), message (std::move (message))
131 {
132 message.shrink_to_fit ();
133 }
134
135 Error (Location locus, std::string message)
136 {
137 Error (Kind::Err, locus, std::move (message));
138 }
139
140 static Error Hint (Location locus, std::string message)
141 {
142 return Error (Kind::Hint, locus, std::move (message));
143 }
144
145 static Error Fatal (Location locus, std::string message)
146 {
147 return Error (Kind::FatalErr, locus, std::move (message));
148 }
149
150 // TODO: the attribute part might be incorrect
151 Error (Location locus, const char *fmt,
152 ...) /*RUST_ATTRIBUTE_GCC_DIAG (2, 3)*/ RUST_ATTRIBUTE_GCC_DIAG (3, 4);
153
154 /**
155 * printf-like overload of Error::Hint
156 */
157 static Error Hint (Location locus, const char *fmt, ...)
158 RUST_ATTRIBUTE_GCC_DIAG (2, 3);
159
160 /**
161 * printf-like overload of Error::Fatal
162 */
163 static Error Fatal (Location locus, const char *fmt, ...)
164 RUST_ATTRIBUTE_GCC_DIAG (2, 3);
165
166 void emit () const
167 {
168 switch (kind)
169 {
170 case Kind::Hint:
171 rust_inform (locus, "%s", message.c_str ());
172 break;
173 case Kind::Err:
174 rust_error_at (locus, "%s", message.c_str ());
175 break;
176 case Kind::FatalErr:
177 rust_fatal_error (locus, "%s", message.c_str ());
178 break;
179 }
180 }
181 };
182 } // namespace Rust
183
184 // rust_debug uses normal printf formatting, not GCC diagnostic formatting.
185 #define rust_debug(...) rust_debug_loc (Location (), __VA_ARGS__)
186
187 // rust_sorry_at wraps GCC diagnostic "sorry_at" to accept "Location" instead of
188 // "location_t"
189 #define rust_sorry_at(location, ...) \
190 sorry_at (location.gcc_location (), __VA_ARGS__)
191
192 void
193 rust_debug_loc (const Location location, const char *fmt,
194 ...) ATTRIBUTE_PRINTF_2;
195
196 #endif // !defined(RUST_DIAGNOSTICS_H)