34 class Bail :
public std::exception {
41 const char*
what() const noexcept
override {
return what_.c_str(); }
77 const auto&
msgs()
const {
return msgs_; }
78 bool empty()
const {
return msgs_.empty(); }
80 size_t num_errors()
const {
return num_[size_t(Tag::Error)]; }
82 size_t num_notes()
const {
return num_[size_t(Tag::Note)]; }
98 template<
class... Args>
Error&
msg(
Loc loc,
Tag tag, std::format_string<Args...> s, Args&&... args) {
99 msg_(loc, tag, [&] {
return std::vformat(s.get(), std::make_format_args(args...)); });
103 template<
class... Args>
Error&
error(
Loc loc, std::format_string<Args...> s, Args&&... args) {
return msg(loc, Tag::Error, s, std::forward<Args>(args)...); }
104 template<
class... Args>
Error&
warn (
Loc loc, std::format_string<Args...> s, Args&&... args) {
return msg(loc, Tag::Warn, s, std::forward<Args>(args)...); }
107 template<
class... Args>
Error&
note(std::format_string<Args...> s, Args&&... args) {
108 note_(
Loc(), [&] {
return std::vformat(s.get(), std::make_format_args(args...)); });
116 template<
class... Args>
Error&
note(
Loc loc, std::format_string<Args...> s, Args&&... args) {
117 if (loc && (loc & primary_loc_()))
return *
this;
118 note_(loc, [&] {
return std::vformat(s.get(), std::make_format_args(args...)); });
134 std::string
str(std::ostream& os = std::cerr)
const {
136 auto oss = std::ostringstream();
143 size_t report(std::ostream& os = std::cerr) {
145 if (!
empty()) os << *
this;
151 [[noreturn]]
void bail(std::ostream& os = std::cerr) {
158 void ack(std::ostream& os = std::cerr) {
166 const auto& diag = e.diag();
168 for (
const auto&
msg : e.msgs_) {
170 diag.snippet(os,
msg.loc,
msg.tag);
171 for (
const auto&
note :
msg.notes)
180 const Diag& diag()
const;
183 Loc primary_loc_()
const {
return msgs_.empty() ?
Loc() : msgs_.back().loc; }
185 void msg_(Loc loc, Tag tag,
const std::function<std::string()>& fmt) {
186 assert(tag != Tag::Note &&
"a note belongs to Error::note");
187 const auto& d = diag();
188 if (tag == Tag::Warn && d.werror) tag = Tag::Error;
190 if (tag == Tag::Error && d.max_errors != 0 &&
num_errors() >= d.max_errors) {
191 truncated_ = dropped_ =
true;
197 msgs_.emplace_back(loc, tag, d.render(fmt));
200 void note_(Loc loc,
const std::function<std::string()>& fmt) {
201 if (dropped_)
return;
202 assert(!msgs_.empty() &&
"a note needs an error or warning to attach to");
203 ++num_[size_t(Tag::Note)];
204 msgs_.back().notes.emplace_back(loc, diag().render(fmt));
207 const Driver* driver_;
208 std::vector<Msg> msgs_;
209 std::array<size_t, 3> num_ = {};
210 bool truncated_ =
false;
211 bool dropped_ =
false;
How a diagnostic lays out - and how much of it an Error keeps.
virtual void summary(std::ostream &, size_t num_errors, size_t num_warnings, bool truncated) const
Bail(std::string what, size_t num_errors, size_t num_warnings)
size_t num_warnings() const
size_t num_errors() const
friend std::ostream & operator<<(std::ostream &os, const Bail &bail)
const char * what() const noexcept override
Error(const Driver &driver)
A sink of your own; Driver::error is the one every frontend building block already reports to.
std::string str(std::ostream &os=std::cerr) const
Renders everything collected so far the way it would appear on os; os only decides the coloring.
Error & msg(Loc loc, Tag tag, const std::function< std::string()> &fmt)
void ack(std::ostream &os=std::cerr)
If errors occurred, Error::bail; otherwise Error::report any warnings to os.
const auto & msgs() const
void bail(std::ostream &os=std::cerr)
Claims everything collected so far and throws it as a Bail rendered for os.
bool truncated() const
Did Diag::max_errors drop anything?
Error & msg(Loc loc, Tag tag, std::format_string< Args... > s, Args &&... args)
Error & warn(Loc loc, std::format_string< Args... > s, Args &&... args)
friend std::ostream & operator<<(std::ostream &os, const Error &e)
Hands every Msg, its Notes, and the closing summary to Diag.
size_t report(std::ostream &os=std::cerr)
Streams everything collected so far to os and claims it.
size_t num_warnings() const
Error & note(std::format_string< Args... > s, Args &&... args)
A = note: continuation of the diagnostic being built; it has no Loc of its own to point at.
size_t num_errors() const
Error & error(Loc loc, std::format_string< Args... > s, Args &&... args)
std::vector< Note > notes
bool ok() const
Nothing recorded that must stop the compilation?
Error & note(Loc loc, std::format_string< Args... > s, Args &&... args)
A Note that points elsewhere; dropped when loc adds nothing.
One Tag::Error or Tag::Warn together with the Notes that belong to it.
A secondary message elaborating a Msg.
Restore< Mode, &mode, &set_mode > ScopedMode
Overrides the color mode for the duration of the scope.
bool use_color(std::ostream &os) noexcept
Whether color escape sequences are emitted for os right now.
basic_ostream_formatter< char > ostream_formatter
Use/derive from this class for "global" variables that you need all over the place.
Location within a Src: the half-open byte range [Loc::begin, Loc::end).
constexpr Loc()=default
Creates an invalid Location.