mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
The various decls relating to rich_location are in libcpp/include/line-map.h, but they don't relate to line maps. Split them out to their own header: libcpp/include/rich-location.h No functional change intended. gcc/ChangeLog: * Makefile.in (CPPLIB_H): Add libcpp/include/rich-location.h. * coretypes.h (class rich_location): New forward decl. gcc/analyzer/ChangeLog: * analyzer.h: Include "rich-location.h". gcc/c-family/ChangeLog: * c-lex.cc: Include "rich-location.h". gcc/cp/ChangeLog: * mapper-client.cc: Include "rich-location.h". gcc/ChangeLog: * diagnostic.h: Include "rich-location.h". * edit-context.h (class fixit_hint): New forward decl. * gcc-rich-location.h: Include "rich-location.h". * genmatch.cc: Likewise. * pretty-print.h: Likewise. gcc/rust/ChangeLog: * rust-location.h: Include "rich-location.h". libcpp/ChangeLog: * Makefile.in (TAGS_SOURCES): Add "include/rich-location.h". * include/cpplib.h (class rich_location): New forward decl. * include/line-map.h (class range_label) (enum range_display_kind, struct location_range) (class semi_embedded_vec, class rich_location, class label_text) (class range_label, class fixit_hint): Move to... * include/rich-location.h: ...this new file. * internal.h: Include "rich-location.h". Signed-off-by: David Malcolm <dmalcolm@redhat.com>
1093 lines
34 KiB
C++
1093 lines
34 KiB
C++
/* Various declarations for language-independent diagnostics subroutines.
|
|
Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
|
Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef GCC_DIAGNOSTIC_H
|
|
#define GCC_DIAGNOSTIC_H
|
|
|
|
#include "rich-location.h"
|
|
#include "pretty-print.h"
|
|
#include "diagnostic-core.h"
|
|
|
|
namespace text_art
|
|
{
|
|
class theme;
|
|
} // namespace text_art
|
|
|
|
/* An enum for controlling what units to use for the column number
|
|
when diagnostics are output, used by the -fdiagnostics-column-unit option.
|
|
Tabs will be expanded or not according to the value of -ftabstop. The origin
|
|
(default 1) is controlled by -fdiagnostics-column-origin. */
|
|
|
|
enum diagnostics_column_unit
|
|
{
|
|
/* The default from GCC 11 onwards: display columns. */
|
|
DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
|
|
|
|
/* The behavior in GCC 10 and earlier: simple bytes. */
|
|
DIAGNOSTICS_COLUMN_UNIT_BYTE
|
|
};
|
|
|
|
/* An enum for controlling how to print non-ASCII characters/bytes when
|
|
a diagnostic suggests escaping the source code on output. */
|
|
|
|
enum diagnostics_escape_format
|
|
{
|
|
/* Escape non-ASCII Unicode characters in the form <U+XXXX> and
|
|
non-UTF-8 bytes in the form <XX>. */
|
|
DIAGNOSTICS_ESCAPE_FORMAT_UNICODE,
|
|
|
|
/* Escape non-ASCII bytes in the form <XX> (thus showing the underlying
|
|
encoding of non-ASCII Unicode characters). */
|
|
DIAGNOSTICS_ESCAPE_FORMAT_BYTES
|
|
};
|
|
|
|
/* Enum for overriding the standard output format. */
|
|
|
|
enum diagnostics_output_format
|
|
{
|
|
/* The default: textual output. */
|
|
DIAGNOSTICS_OUTPUT_FORMAT_TEXT,
|
|
|
|
/* JSON-based output, to stderr. */
|
|
DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR,
|
|
|
|
/* JSON-based output, to a file. */
|
|
DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE,
|
|
|
|
/* SARIF-based output, to stderr. */
|
|
DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR,
|
|
|
|
/* SARIF-based output, to a file. */
|
|
DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
|
|
};
|
|
|
|
/* An enum for controlling how diagnostic_paths should be printed. */
|
|
enum diagnostic_path_format
|
|
{
|
|
/* Don't print diagnostic_paths. */
|
|
DPF_NONE,
|
|
|
|
/* Print diagnostic_paths by emitting a separate "note" for every event
|
|
in the path. */
|
|
DPF_SEPARATE_EVENTS,
|
|
|
|
/* Print diagnostic_paths by consolidating events together where they
|
|
are close enough, and printing such runs of events with multiple
|
|
calls to diagnostic_show_locus, showing the individual events in
|
|
each run via labels in the source. */
|
|
DPF_INLINE_EVENTS
|
|
};
|
|
|
|
/* An enum for capturing values of GCC_EXTRA_DIAGNOSTIC_OUTPUT,
|
|
and for -fdiagnostics-parseable-fixits. */
|
|
|
|
enum diagnostics_extra_output_kind
|
|
{
|
|
/* No extra output, or an unrecognized value. */
|
|
EXTRA_DIAGNOSTIC_OUTPUT_none,
|
|
|
|
/* Emit fix-it hints using the "fixits-v1" format, equivalent to
|
|
-fdiagnostics-parseable-fixits. */
|
|
EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1,
|
|
|
|
/* Emit fix-it hints using the "fixits-v2" format. */
|
|
EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
|
|
};
|
|
|
|
/* Values for -fdiagnostics-text-art-charset=. */
|
|
|
|
enum diagnostic_text_art_charset
|
|
{
|
|
/* No text art diagrams shall be emitted. */
|
|
DIAGNOSTICS_TEXT_ART_CHARSET_NONE,
|
|
|
|
/* Use pure ASCII for text art diagrams. */
|
|
DIAGNOSTICS_TEXT_ART_CHARSET_ASCII,
|
|
|
|
/* Use ASCII + conservative use of other unicode characters
|
|
in text art diagrams. */
|
|
DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE,
|
|
|
|
/* Use Emoji. */
|
|
DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
|
|
};
|
|
|
|
/* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
|
|
its context and its KIND (ice, error, warning, note, ...) See complete
|
|
list in diagnostic.def. */
|
|
struct diagnostic_info
|
|
{
|
|
diagnostic_info ()
|
|
: message (), richloc (), metadata (), x_data (), kind (), option_index (),
|
|
m_iinfo ()
|
|
{ }
|
|
|
|
/* Text to be formatted. */
|
|
text_info message;
|
|
|
|
/* The location at which the diagnostic is to be reported. */
|
|
rich_location *richloc;
|
|
|
|
/* An optional bundle of metadata associated with the diagnostic
|
|
(or NULL). */
|
|
const diagnostic_metadata *metadata;
|
|
|
|
/* Auxiliary data for client. */
|
|
void *x_data;
|
|
/* The kind of diagnostic it is about. */
|
|
diagnostic_t kind;
|
|
/* Which OPT_* directly controls this diagnostic. */
|
|
int option_index;
|
|
|
|
/* Inlining context containing locations for each call site along
|
|
the inlining stack. */
|
|
struct inlining_info
|
|
{
|
|
/* Locations along the inlining stack. */
|
|
auto_vec<location_t, 8> m_ilocs;
|
|
/* The abstract origin of the location. */
|
|
void *m_ao;
|
|
/* Set if every M_ILOCS element is in a system header. */
|
|
bool m_allsyslocs;
|
|
} m_iinfo;
|
|
};
|
|
|
|
/* Forward declarations. */
|
|
typedef void (*diagnostic_starter_fn) (diagnostic_context *,
|
|
diagnostic_info *);
|
|
|
|
typedef void (*diagnostic_start_span_fn) (diagnostic_context *,
|
|
expanded_location);
|
|
|
|
typedef void (*diagnostic_finalizer_fn) (diagnostic_context *,
|
|
diagnostic_info *,
|
|
diagnostic_t);
|
|
|
|
typedef int (*diagnostic_option_enabled_cb) (int, unsigned, void *);
|
|
typedef char *(*diagnostic_make_option_name_cb) (const diagnostic_context *,
|
|
int,
|
|
diagnostic_t,
|
|
diagnostic_t);
|
|
typedef char *(*diagnostic_make_option_url_cb) (const diagnostic_context *,
|
|
int);
|
|
|
|
class edit_context;
|
|
namespace json { class value; }
|
|
class diagnostic_client_data_hooks;
|
|
class logical_location;
|
|
class diagnostic_diagram;
|
|
|
|
/* Abstract base class for a particular output format for diagnostics;
|
|
each value of -fdiagnostics-output-format= will have its own
|
|
implementation. */
|
|
|
|
class diagnostic_output_format
|
|
{
|
|
public:
|
|
virtual ~diagnostic_output_format () {}
|
|
|
|
virtual void on_begin_group () = 0;
|
|
virtual void on_end_group () = 0;
|
|
virtual void on_begin_diagnostic (diagnostic_info *) = 0;
|
|
virtual void on_end_diagnostic (diagnostic_info *,
|
|
diagnostic_t orig_diag_kind) = 0;
|
|
virtual void on_diagram (const diagnostic_diagram &diagram) = 0;
|
|
|
|
protected:
|
|
diagnostic_output_format (diagnostic_context &context)
|
|
: m_context (context)
|
|
{}
|
|
|
|
diagnostic_context &m_context;
|
|
};
|
|
|
|
/* Subclass of diagnostic_output_format for classic text-based output
|
|
to stderr.
|
|
|
|
Uses diagnostic_context.m_text_callbacks to provide client-specific
|
|
textual output (e.g. include paths, macro expansions, etc). */
|
|
|
|
class diagnostic_text_output_format : public diagnostic_output_format
|
|
{
|
|
public:
|
|
diagnostic_text_output_format (diagnostic_context &context)
|
|
: diagnostic_output_format (context)
|
|
{}
|
|
~diagnostic_text_output_format ();
|
|
void on_begin_group () override {}
|
|
void on_end_group () override {}
|
|
void on_begin_diagnostic (diagnostic_info *) override;
|
|
void on_end_diagnostic (diagnostic_info *,
|
|
diagnostic_t orig_diag_kind) override;
|
|
void on_diagram (const diagnostic_diagram &diagram) override;
|
|
};
|
|
|
|
/* A stack of sets of classifications: each entry in the stack is
|
|
a mapping from option index to diagnostic severity that can be changed
|
|
via pragmas. The stack can be pushed and popped. */
|
|
|
|
class diagnostic_option_classifier
|
|
{
|
|
public:
|
|
void init (int n_opts);
|
|
void fini ();
|
|
|
|
/* Save all diagnostic classifications in a stack. */
|
|
void push ();
|
|
|
|
/* Restore the topmost classification set off the stack. If the stack
|
|
is empty, revert to the state based on command line parameters. */
|
|
void pop (location_t where);
|
|
|
|
bool option_unspecified_p (int opt) const
|
|
{
|
|
return get_current_override (opt) == DK_UNSPECIFIED;
|
|
}
|
|
|
|
diagnostic_t get_current_override (int opt) const
|
|
{
|
|
gcc_assert (opt < m_n_opts);
|
|
return m_classify_diagnostic[opt];
|
|
}
|
|
|
|
diagnostic_t
|
|
classify_diagnostic (const diagnostic_context *context,
|
|
int option_index,
|
|
diagnostic_t new_kind,
|
|
location_t where);
|
|
|
|
diagnostic_t
|
|
update_effective_level_from_pragmas (diagnostic_info *diagnostic) const;
|
|
|
|
private:
|
|
/* Each time a diagnostic's classification is changed with a pragma,
|
|
we record the change and the location of the change in an array of
|
|
these structs. */
|
|
struct diagnostic_classification_change_t
|
|
{
|
|
location_t location;
|
|
int option;
|
|
diagnostic_t kind;
|
|
};
|
|
|
|
int m_n_opts;
|
|
|
|
/* For each option index that can be passed to warning() et al
|
|
(OPT_* from options.h when using this code with the core GCC
|
|
options), this array may contain a new kind that the diagnostic
|
|
should be changed to before reporting, or DK_UNSPECIFIED to leave
|
|
it as the reported kind, or DK_IGNORED to not report it at
|
|
all. */
|
|
diagnostic_t *m_classify_diagnostic;
|
|
|
|
/* History of all changes to the classifications above. This list
|
|
is stored in location-order, so we can search it, either
|
|
binary-wise or end-to-front, to find the most recent
|
|
classification for a given diagnostic, given the location of the
|
|
diagnostic. */
|
|
diagnostic_classification_change_t *m_classification_history;
|
|
|
|
/* The size of the above array. */
|
|
int m_n_classification_history;
|
|
|
|
/* For pragma push/pop. */
|
|
int *m_push_list;
|
|
int m_n_push;
|
|
};
|
|
|
|
/* A bundle of options relating to printing the user's source code
|
|
(potentially with a margin, underlining, labels, etc). */
|
|
|
|
struct diagnostic_source_printing_options
|
|
{
|
|
/* True if we should print the source line with a caret indicating
|
|
the location.
|
|
Corresponds to -fdiagnostics-show-caret. */
|
|
bool enabled;
|
|
|
|
/* Maximum width of the source line printed. */
|
|
int max_width;
|
|
|
|
/* Character used at the caret when printing source locations. */
|
|
char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
|
|
|
|
/* When printing source code, should the characters at carets and ranges
|
|
be colorized? (assuming colorization is on at all).
|
|
This should be true for frontends that generate range information
|
|
(so that the ranges of code are colorized),
|
|
and false for frontends that merely specify points within the
|
|
source code (to avoid e.g. colorizing just the first character in
|
|
a token, which would look strange). */
|
|
bool colorize_source_p;
|
|
|
|
/* When printing source code, should labelled ranges be printed?
|
|
Corresponds to -fdiagnostics-show-labels. */
|
|
bool show_labels_p;
|
|
|
|
/* When printing source code, should there be a left-hand margin
|
|
showing line numbers?
|
|
Corresponds to -fdiagnostics-show-line-numbers. */
|
|
bool show_line_numbers_p;
|
|
|
|
/* If printing source code, what should the minimum width of the margin
|
|
be? Line numbers will be right-aligned, and padded to this width.
|
|
Corresponds to -fdiagnostics-minimum-margin-width=VALUE. */
|
|
int min_margin_width;
|
|
|
|
/* Usable by plugins; if true, print a debugging ruler above the
|
|
source output. */
|
|
bool show_ruler_p;
|
|
};
|
|
|
|
/* This data structure bundles altogether any information relevant to
|
|
the context of a diagnostic message. */
|
|
class diagnostic_context
|
|
{
|
|
public:
|
|
/* Give access to m_text_callbacks. */
|
|
friend diagnostic_starter_fn &
|
|
diagnostic_starter (diagnostic_context *context);
|
|
friend diagnostic_start_span_fn &
|
|
diagnostic_start_span (diagnostic_context *context);
|
|
friend diagnostic_finalizer_fn &
|
|
diagnostic_finalizer (diagnostic_context *context);
|
|
|
|
typedef void (*ice_handler_callback_t) (diagnostic_context *);
|
|
typedef void (*set_locations_callback_t) (diagnostic_context *,
|
|
diagnostic_info *);
|
|
|
|
void initialize (int n_opts);
|
|
void color_init (int value);
|
|
void urls_init (int value);
|
|
|
|
void finish ();
|
|
|
|
void set_set_locations_callback (set_locations_callback_t cb)
|
|
{
|
|
m_set_locations_cb = cb;
|
|
}
|
|
|
|
void
|
|
initialize_input_context (diagnostic_input_charset_callback ccb,
|
|
bool should_skip_bom);
|
|
|
|
void begin_group ();
|
|
void end_group ();
|
|
|
|
bool warning_enabled_at (location_t loc, int opt);
|
|
|
|
bool option_unspecified_p (int opt) const
|
|
{
|
|
return m_option_classifier.option_unspecified_p (opt);
|
|
}
|
|
|
|
bool report_diagnostic (diagnostic_info *);
|
|
|
|
void report_current_module (location_t where);
|
|
|
|
void check_max_errors (bool flush);
|
|
void action_after_output (diagnostic_t diag_kind);
|
|
|
|
diagnostic_t
|
|
classify_diagnostic (int option_index,
|
|
diagnostic_t new_kind,
|
|
location_t where)
|
|
{
|
|
return m_option_classifier.classify_diagnostic (this,
|
|
option_index,
|
|
new_kind,
|
|
where);
|
|
}
|
|
|
|
void push_diagnostics (location_t where ATTRIBUTE_UNUSED)
|
|
{
|
|
m_option_classifier.push ();
|
|
}
|
|
void pop_diagnostics (location_t where)
|
|
{
|
|
m_option_classifier.pop (where);
|
|
}
|
|
|
|
void maybe_show_locus (const rich_location &richloc,
|
|
diagnostic_t diagnostic_kind,
|
|
pretty_printer *pp);
|
|
|
|
void emit_diagram (const diagnostic_diagram &diagram);
|
|
|
|
/* Various setters for use by option-handling logic. */
|
|
void set_output_format (diagnostic_output_format *output_format);
|
|
void set_text_art_charset (enum diagnostic_text_art_charset charset);
|
|
void set_client_data_hooks (diagnostic_client_data_hooks *hooks);
|
|
void set_urlifier (urlifier *);
|
|
void create_edit_context ();
|
|
void set_warning_as_error_requested (bool val)
|
|
{
|
|
m_warning_as_error_requested = val;
|
|
}
|
|
void set_report_bug (bool val) { m_report_bug = val; }
|
|
void set_extra_output_kind (enum diagnostics_extra_output_kind kind)
|
|
{
|
|
m_extra_output_kind = kind;
|
|
}
|
|
void set_show_cwe (bool val) { m_show_cwe = val; }
|
|
void set_show_rules (bool val) { m_show_rules = val; }
|
|
void set_path_format (enum diagnostic_path_format val)
|
|
{
|
|
m_path_format = val;
|
|
}
|
|
void set_show_path_depths (bool val) { m_show_path_depths = val; }
|
|
void set_show_option_requested (bool val) { m_show_option_requested = val; }
|
|
void set_max_errors (int val) { m_max_errors = val; }
|
|
void set_escape_format (enum diagnostics_escape_format val)
|
|
{
|
|
m_escape_format = val;
|
|
}
|
|
void set_ice_handler_callback (ice_handler_callback_t cb)
|
|
{
|
|
m_ice_handler_cb = cb;
|
|
}
|
|
|
|
/* Various accessors. */
|
|
bool warning_as_error_requested_p () const
|
|
{
|
|
return m_warning_as_error_requested;
|
|
}
|
|
bool show_path_depths_p () const { return m_show_path_depths; }
|
|
enum diagnostic_path_format get_path_format () const { return m_path_format; }
|
|
enum diagnostics_escape_format get_escape_format () const
|
|
{
|
|
return m_escape_format;
|
|
}
|
|
|
|
file_cache &
|
|
get_file_cache () const
|
|
{
|
|
gcc_assert (m_file_cache);
|
|
return *m_file_cache;
|
|
}
|
|
|
|
edit_context *get_edit_context () const
|
|
{
|
|
return m_edit_context_ptr;
|
|
}
|
|
const diagnostic_client_data_hooks *get_client_data_hooks ()
|
|
{
|
|
return m_client_data_hooks;
|
|
}
|
|
text_art::theme *get_diagram_theme () const { return m_diagrams.m_theme; }
|
|
|
|
int converted_column (expanded_location s) const;
|
|
|
|
int &diagnostic_count (diagnostic_t kind)
|
|
{
|
|
return m_diagnostic_count[kind];
|
|
}
|
|
|
|
/* Option-related member functions. */
|
|
inline bool option_enabled_p (int option_index) const
|
|
{
|
|
if (!m_option_callbacks.m_option_enabled_cb)
|
|
return true;
|
|
return m_option_callbacks.m_option_enabled_cb
|
|
(option_index,
|
|
m_option_callbacks.m_lang_mask,
|
|
m_option_callbacks.m_option_state);
|
|
}
|
|
|
|
inline char *make_option_name (int option_index,
|
|
diagnostic_t orig_diag_kind,
|
|
diagnostic_t diag_kind) const
|
|
{
|
|
if (!m_option_callbacks.m_make_option_name_cb)
|
|
return nullptr;
|
|
return m_option_callbacks.m_make_option_name_cb (this, option_index,
|
|
orig_diag_kind,
|
|
diag_kind);
|
|
}
|
|
|
|
inline char *make_option_url (int option_index) const
|
|
{
|
|
if (!m_option_callbacks.m_make_option_url_cb)
|
|
return nullptr;
|
|
return m_option_callbacks.m_make_option_url_cb (this, option_index);
|
|
}
|
|
|
|
void
|
|
set_option_hooks (diagnostic_option_enabled_cb option_enabled_cb,
|
|
void *option_state,
|
|
diagnostic_make_option_name_cb make_option_name_cb,
|
|
diagnostic_make_option_url_cb make_option_url_cb,
|
|
unsigned lang_mask);
|
|
|
|
unsigned get_lang_mask () const
|
|
{
|
|
return m_option_callbacks.m_lang_mask;
|
|
}
|
|
|
|
private:
|
|
bool includes_seen_p (const line_map_ordinary *map);
|
|
|
|
void print_any_cwe (const diagnostic_info &diagnostic);
|
|
void print_any_rules (const diagnostic_info &diagnostic);
|
|
void print_option_information (const diagnostic_info &diagnostic,
|
|
diagnostic_t orig_diag_kind);
|
|
|
|
void show_any_path (const diagnostic_info &diagnostic);
|
|
|
|
void error_recursion () ATTRIBUTE_NORETURN;
|
|
|
|
bool diagnostic_enabled (diagnostic_info *diagnostic);
|
|
|
|
void get_any_inlining_info (diagnostic_info *diagnostic);
|
|
|
|
void show_locus (const rich_location &richloc,
|
|
diagnostic_t diagnostic_kind,
|
|
pretty_printer *pp);
|
|
|
|
/* Data members.
|
|
Ideally, all of these would be private and have "m_" prefixes. */
|
|
|
|
public:
|
|
/* Where most of the diagnostic formatting work is done. */
|
|
pretty_printer *printer;
|
|
|
|
private:
|
|
/* Cache of source code. */
|
|
file_cache *m_file_cache;
|
|
|
|
/* The number of times we have issued diagnostics. */
|
|
int m_diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
|
|
|
|
/* True if it has been requested that warnings be treated as errors. */
|
|
bool m_warning_as_error_requested;
|
|
|
|
/* The number of option indexes that can be passed to warning() et
|
|
al. */
|
|
int m_n_opts;
|
|
|
|
/* The stack of sets of overridden diagnostic option severities. */
|
|
diagnostic_option_classifier m_option_classifier;
|
|
|
|
/* True if we should print any CWE identifiers associated with
|
|
diagnostics. */
|
|
bool m_show_cwe;
|
|
|
|
/* True if we should print any rules associated with diagnostics. */
|
|
bool m_show_rules;
|
|
|
|
/* How should diagnostic_path objects be printed. */
|
|
enum diagnostic_path_format m_path_format;
|
|
|
|
/* True if we should print stack depths when printing diagnostic paths. */
|
|
bool m_show_path_depths;
|
|
|
|
/* True if we should print the command line option which controls
|
|
each diagnostic, if known. */
|
|
bool m_show_option_requested;
|
|
|
|
public:
|
|
/* True if we should raise a SIGABRT on errors. */
|
|
bool m_abort_on_error;
|
|
|
|
/* True if we should show the column number on diagnostics. */
|
|
bool m_show_column;
|
|
|
|
/* True if pedwarns are errors. */
|
|
bool m_pedantic_errors;
|
|
|
|
/* True if permerrors are warnings. */
|
|
bool m_permissive;
|
|
|
|
/* The index of the option to associate with turning permerrors into
|
|
warnings. */
|
|
int m_opt_permissive;
|
|
|
|
/* True if errors are fatal. */
|
|
bool m_fatal_errors;
|
|
|
|
/* True if all warnings should be disabled. */
|
|
bool m_inhibit_warnings;
|
|
|
|
/* True if warnings should be given in system headers. */
|
|
bool m_warn_system_headers;
|
|
|
|
private:
|
|
/* Maximum number of errors to report. */
|
|
int m_max_errors;
|
|
|
|
/* Client-supplied callbacks for use in text output. */
|
|
struct {
|
|
/* This function is called before any message is printed out. It is
|
|
responsible for preparing message prefix and such. For example, it
|
|
might say:
|
|
In file included from "/usr/local/include/curses.h:5:
|
|
from "/home/gdr/src/nifty_printer.h:56:
|
|
...
|
|
*/
|
|
diagnostic_starter_fn m_begin_diagnostic;
|
|
|
|
/* This function is called by diagnostic_show_locus in between
|
|
disjoint spans of source code, so that the context can print
|
|
something to indicate that a new span of source code has begun. */
|
|
diagnostic_start_span_fn m_start_span;
|
|
|
|
/* This function is called after the diagnostic message is printed. */
|
|
diagnostic_finalizer_fn m_end_diagnostic;
|
|
} m_text_callbacks;
|
|
|
|
public:
|
|
/* Client hook to report an internal error. */
|
|
void (*m_internal_error) (diagnostic_context *, const char *, va_list *);
|
|
|
|
private:
|
|
/* Client-supplied callbacks for working with options. */
|
|
struct {
|
|
/* Client hook to say whether the option controlling a diagnostic is
|
|
enabled. Returns nonzero if enabled, zero if disabled. */
|
|
diagnostic_option_enabled_cb m_option_enabled_cb;
|
|
|
|
/* Client information to pass as second argument to
|
|
m_option_enabled_cb. */
|
|
void *m_option_state;
|
|
|
|
/* Client hook to return the name of an option that controls a
|
|
diagnostic. Returns malloced memory. The first diagnostic_t
|
|
argument is the kind of diagnostic before any reclassification
|
|
(of warnings as errors, etc.); the second is the kind after any
|
|
reclassification. May return NULL if no name is to be printed.
|
|
May be passed 0 as well as the index of a particular option. */
|
|
diagnostic_make_option_name_cb m_make_option_name_cb;
|
|
|
|
/* Client hook to return a URL describing the option that controls
|
|
a diagnostic. Returns malloced memory. May return NULL if no URL
|
|
is available. May be passed 0 as well as the index of a
|
|
particular option. */
|
|
diagnostic_make_option_url_cb m_make_option_url_cb;
|
|
|
|
/* A copy of lang_hooks.option_lang_mask (). */
|
|
unsigned m_lang_mask;
|
|
} m_option_callbacks;
|
|
|
|
/* An optional hook for adding URLs to quoted text strings in
|
|
diagnostics. Only used for the main diagnostic message. */
|
|
urlifier *m_urlifier;
|
|
|
|
public:
|
|
void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
|
|
json::value *(*m_make_json_for_path) (diagnostic_context *,
|
|
const diagnostic_path *);
|
|
|
|
/* Auxiliary data for client. */
|
|
void *m_client_aux_data;
|
|
|
|
/* Used to detect that the last caret was printed at the same location. */
|
|
location_t m_last_location;
|
|
|
|
private:
|
|
/* Used to detect when the input file stack has changed since last
|
|
described. */
|
|
const line_map_ordinary *m_last_module;
|
|
|
|
int m_lock;
|
|
|
|
public:
|
|
bool m_inhibit_notes_p;
|
|
|
|
diagnostic_source_printing_options m_source_printing;
|
|
|
|
private:
|
|
/* True if -freport-bug option is used. */
|
|
bool m_report_bug;
|
|
|
|
/* Used to specify additional diagnostic output to be emitted after the
|
|
rest of the diagnostic. This is for implementing
|
|
-fdiagnostics-parseable-fixits and GCC_EXTRA_DIAGNOSTIC_OUTPUT. */
|
|
enum diagnostics_extra_output_kind m_extra_output_kind;
|
|
|
|
public:
|
|
/* What units to use when outputting the column number. */
|
|
enum diagnostics_column_unit m_column_unit;
|
|
|
|
/* The origin for the column number (1-based or 0-based typically). */
|
|
int m_column_origin;
|
|
|
|
/* The size of the tabstop for tab expansion. */
|
|
int m_tabstop;
|
|
|
|
private:
|
|
/* How should non-ASCII/non-printable bytes be escaped when
|
|
a diagnostic suggests escaping the source code on output. */
|
|
enum diagnostics_escape_format m_escape_format;
|
|
|
|
/* If non-NULL, an edit_context to which fix-it hints should be
|
|
applied, for generating patches. */
|
|
edit_context *m_edit_context_ptr;
|
|
|
|
/* Fields relating to diagnostic groups. */
|
|
struct {
|
|
/* How many diagnostic_group instances are currently alive. */
|
|
int m_nesting_depth;
|
|
|
|
/* How many diagnostics have been emitted since the bottommost
|
|
diagnostic_group was pushed. */
|
|
int m_emission_count;
|
|
} m_diagnostic_groups;
|
|
|
|
/* How to output diagnostics (text vs a structured format such as JSON).
|
|
Must be non-NULL; owned by context. */
|
|
diagnostic_output_format *m_output_format;
|
|
|
|
/* Callback to set the locations of call sites along the inlining
|
|
stack corresponding to a diagnostic location. Needed to traverse
|
|
the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
|
|
of a diagnostic's location. */
|
|
set_locations_callback_t m_set_locations_cb;
|
|
|
|
/* Optional callback for attempting to handle ICEs gracefully. */
|
|
ice_handler_callback_t m_ice_handler_cb;
|
|
|
|
/* Include files that diagnostic_report_current_module has already listed the
|
|
include path for. */
|
|
hash_set<location_t, false, location_hash> *m_includes_seen;
|
|
|
|
/* A bundle of hooks for providing data to the context about its client
|
|
e.g. version information, plugins, etc.
|
|
Used by SARIF output to give metadata about the client that's
|
|
producing diagnostics. */
|
|
diagnostic_client_data_hooks *m_client_data_hooks;
|
|
|
|
/* Support for diagrams. */
|
|
struct
|
|
{
|
|
/* Theme to use when generating diagrams.
|
|
Can be NULL (if text art is disabled). */
|
|
text_art::theme *m_theme;
|
|
|
|
} m_diagrams;
|
|
};
|
|
|
|
inline void
|
|
diagnostic_inhibit_notes (diagnostic_context * context)
|
|
{
|
|
context->m_inhibit_notes_p = true;
|
|
}
|
|
|
|
|
|
/* Client supplied function to announce a diagnostic
|
|
(for text-based diagnostic output). */
|
|
inline diagnostic_starter_fn &
|
|
diagnostic_starter (diagnostic_context *context)
|
|
{
|
|
return context->m_text_callbacks.m_begin_diagnostic;
|
|
}
|
|
|
|
/* Client supplied function called between disjoint spans of source code,
|
|
so that the context can print
|
|
something to indicate that a new span of source code has begun. */
|
|
inline diagnostic_start_span_fn &
|
|
diagnostic_start_span (diagnostic_context *context)
|
|
{
|
|
return context->m_text_callbacks.m_start_span;
|
|
}
|
|
|
|
/* Client supplied function called after a diagnostic message is
|
|
displayed (for text-based diagnostic output). */
|
|
inline diagnostic_finalizer_fn &
|
|
diagnostic_finalizer (diagnostic_context *context)
|
|
{
|
|
return context->m_text_callbacks.m_end_diagnostic;
|
|
}
|
|
|
|
/* Extension hooks for client. */
|
|
#define diagnostic_context_auxiliary_data(DC) (DC)->m_client_aux_data
|
|
#define diagnostic_info_auxiliary_data(DI) (DI)->x_data
|
|
|
|
/* Same as pp_format_decoder. Works on 'diagnostic_context *'. */
|
|
#define diagnostic_format_decoder(DC) ((DC)->printer->format_decoder)
|
|
|
|
/* Same as output_prefixing_rule. Works on 'diagnostic_context *'. */
|
|
#define diagnostic_prefixing_rule(DC) ((DC)->printer->wrapping.rule)
|
|
|
|
/* Raise SIGABRT on any diagnostic of severity DK_ERROR or higher. */
|
|
inline void
|
|
diagnostic_abort_on_error (diagnostic_context *context)
|
|
{
|
|
context->m_abort_on_error = true;
|
|
}
|
|
|
|
/* This diagnostic_context is used by front-ends that directly output
|
|
diagnostic messages without going through `error', `warning',
|
|
and similar functions. */
|
|
extern diagnostic_context *global_dc;
|
|
|
|
/* Returns whether the diagnostic framework has been intialized already and is
|
|
ready for use. */
|
|
inline bool
|
|
diagnostic_ready_p ()
|
|
{
|
|
return global_dc->printer != nullptr;
|
|
}
|
|
|
|
/* The number of errors that have been issued so far. Ideally, these
|
|
would take a diagnostic_context as an argument. */
|
|
#define errorcount global_dc->diagnostic_count (DK_ERROR)
|
|
/* Similarly, but for warnings. */
|
|
#define warningcount global_dc->diagnostic_count (DK_WARNING)
|
|
/* Similarly, but for warnings promoted to errors. */
|
|
#define werrorcount global_dc->diagnostic_count (DK_WERROR)
|
|
/* Similarly, but for sorrys. */
|
|
#define sorrycount global_dc->diagnostic_count (DK_SORRY)
|
|
|
|
/* Returns nonzero if warnings should be emitted. */
|
|
#define diagnostic_report_warnings_p(DC, LOC) \
|
|
(!(DC)->m_inhibit_warnings \
|
|
&& !(in_system_header_at (LOC) && !(DC)->m_warn_system_headers))
|
|
|
|
/* Override the option index to be used for reporting a
|
|
diagnostic. */
|
|
|
|
inline void
|
|
diagnostic_override_option_index (diagnostic_info *info, int optidx)
|
|
{
|
|
info->option_index = optidx;
|
|
}
|
|
|
|
/* Diagnostic related functions. */
|
|
|
|
inline void
|
|
diagnostic_initialize (diagnostic_context *context, int n_opts)
|
|
{
|
|
context->initialize (n_opts);
|
|
}
|
|
|
|
inline void
|
|
diagnostic_color_init (diagnostic_context *context, int value = -1)
|
|
{
|
|
context->color_init (value);
|
|
}
|
|
|
|
inline void
|
|
diagnostic_urls_init (diagnostic_context *context, int value = -1)
|
|
{
|
|
context->urls_init (value);
|
|
}
|
|
|
|
inline void
|
|
diagnostic_finish (diagnostic_context *context)
|
|
{
|
|
context->finish ();
|
|
}
|
|
|
|
inline void
|
|
diagnostic_report_current_module (diagnostic_context *context,
|
|
location_t where)
|
|
{
|
|
context->report_current_module (where);
|
|
}
|
|
|
|
inline void
|
|
diagnostic_show_locus (diagnostic_context *context,
|
|
rich_location *richloc,
|
|
diagnostic_t diagnostic_kind,
|
|
pretty_printer *pp = nullptr)
|
|
{
|
|
gcc_assert (richloc);
|
|
context->maybe_show_locus (*richloc, diagnostic_kind, pp);
|
|
}
|
|
|
|
/* Because we read source files a second time after the frontend did it the
|
|
first time, we need to know how the frontend handled things like character
|
|
set conversion and UTF-8 BOM stripping, in order to make everything
|
|
consistent. This function needs to be called by each frontend that requires
|
|
non-default behavior, to inform the diagnostics infrastructure how input is
|
|
to be processed. The default behavior is to do no conversion and not to
|
|
strip a UTF-8 BOM.
|
|
|
|
The callback should return the input charset to be used to convert the given
|
|
file's contents to UTF-8, or it should return NULL if no conversion is needed
|
|
for this file. SHOULD_SKIP_BOM only applies in case no conversion was
|
|
performed, and if true, it will cause a UTF-8 BOM to be skipped at the
|
|
beginning of the file. (In case a conversion was performed, the BOM is
|
|
rather skipped as part of the conversion process.) */
|
|
|
|
inline void
|
|
diagnostic_initialize_input_context (diagnostic_context *context,
|
|
diagnostic_input_charset_callback ccb,
|
|
bool should_skip_bom)
|
|
{
|
|
context->initialize_input_context (ccb, should_skip_bom);
|
|
}
|
|
|
|
/* Force diagnostics controlled by OPTIDX to be kind KIND. */
|
|
inline diagnostic_t
|
|
diagnostic_classify_diagnostic (diagnostic_context *context,
|
|
int optidx,
|
|
diagnostic_t kind,
|
|
location_t where)
|
|
{
|
|
return context->classify_diagnostic (optidx, kind, where);
|
|
}
|
|
|
|
inline void
|
|
diagnostic_push_diagnostics (diagnostic_context *context,
|
|
location_t where)
|
|
{
|
|
context->push_diagnostics (where);
|
|
}
|
|
inline void
|
|
diagnostic_pop_diagnostics (diagnostic_context *context,
|
|
location_t where)
|
|
{
|
|
context->pop_diagnostics (where);
|
|
}
|
|
|
|
/* Report a diagnostic message (an error or a warning) as specified by
|
|
DC. This function is *the* subroutine in terms of which front-ends
|
|
should implement their specific diagnostic handling modules. The
|
|
front-end independent format specifiers are exactly those described
|
|
in the documentation of output_format.
|
|
Return true if a diagnostic was printed, false otherwise. */
|
|
|
|
inline bool
|
|
diagnostic_report_diagnostic (diagnostic_context *context,
|
|
diagnostic_info *diagnostic)
|
|
{
|
|
return context->report_diagnostic (diagnostic);
|
|
}
|
|
|
|
#ifdef ATTRIBUTE_GCC_DIAG
|
|
extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
|
|
rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
|
|
extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
|
|
va_list *, rich_location *,
|
|
diagnostic_t)
|
|
ATTRIBUTE_GCC_DIAG(2,0);
|
|
extern void diagnostic_append_note (diagnostic_context *, location_t,
|
|
const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
|
|
#endif
|
|
extern char *diagnostic_build_prefix (diagnostic_context *, const diagnostic_info *);
|
|
void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
|
|
void default_diagnostic_start_span_fn (diagnostic_context *,
|
|
expanded_location);
|
|
void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *,
|
|
diagnostic_t);
|
|
void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
|
|
|
|
inline void
|
|
diagnostic_action_after_output (diagnostic_context *context,
|
|
diagnostic_t diag_kind)
|
|
{
|
|
context->action_after_output (diag_kind);
|
|
}
|
|
|
|
inline void
|
|
diagnostic_check_max_errors (diagnostic_context *context, bool flush = false)
|
|
{
|
|
context->check_max_errors (flush);
|
|
}
|
|
|
|
int get_terminal_width (void);
|
|
|
|
/* Return the location associated to this diagnostic. Parameter WHICH
|
|
specifies which location. By default, expand the first one. */
|
|
|
|
inline location_t
|
|
diagnostic_location (const diagnostic_info * diagnostic, int which = 0)
|
|
{
|
|
return diagnostic->message.get_location (which);
|
|
}
|
|
|
|
/* Return the number of locations to be printed in DIAGNOSTIC. */
|
|
|
|
inline unsigned int
|
|
diagnostic_num_locations (const diagnostic_info * diagnostic)
|
|
{
|
|
return diagnostic->message.m_richloc->get_num_locations ();
|
|
}
|
|
|
|
/* Expand the location of this diagnostic. Use this function for
|
|
consistency. Parameter WHICH specifies which location. By default,
|
|
expand the first one. */
|
|
|
|
inline expanded_location
|
|
diagnostic_expand_location (const diagnostic_info * diagnostic, int which = 0)
|
|
{
|
|
return diagnostic->richloc->get_expanded_location (which);
|
|
}
|
|
|
|
/* This is somehow the right-side margin of a caret line, that is, we
|
|
print at least these many characters after the position pointed at
|
|
by the caret. */
|
|
const int CARET_LINE_MARGIN = 10;
|
|
|
|
/* Return true if the two locations can be represented within the same
|
|
caret line. This is used to build a prefix and also to determine
|
|
whether to print one or two caret lines. */
|
|
|
|
inline bool
|
|
diagnostic_same_line (const diagnostic_context *context,
|
|
expanded_location s1, expanded_location s2)
|
|
{
|
|
return (s2.column && s1.line == s2.line
|
|
&& (context->m_source_printing.max_width - CARET_LINE_MARGIN
|
|
> abs (s1.column - s2.column)));
|
|
}
|
|
|
|
extern const char *diagnostic_get_color_for_kind (diagnostic_t kind);
|
|
|
|
/* Pure text formatting support functions. */
|
|
extern char *file_name_as_prefix (diagnostic_context *, const char *);
|
|
|
|
extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
|
|
|
|
extern void diagnostic_output_format_init (diagnostic_context *,
|
|
const char *base_file_name,
|
|
enum diagnostics_output_format);
|
|
extern void diagnostic_output_format_init_json_stderr (diagnostic_context *context);
|
|
extern void diagnostic_output_format_init_json_file (diagnostic_context *context,
|
|
const char *base_file_name);
|
|
extern void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context);
|
|
extern void diagnostic_output_format_init_sarif_file (diagnostic_context *context,
|
|
const char *base_file_name);
|
|
extern void diagnostic_output_format_init_sarif_stream (diagnostic_context *context,
|
|
FILE *stream);
|
|
|
|
/* Compute the number of digits in the decimal representation of an integer. */
|
|
extern int num_digits (int);
|
|
|
|
extern json::value *json_from_expanded_location (diagnostic_context *context,
|
|
location_t loc);
|
|
|
|
inline bool
|
|
warning_enabled_at (location_t loc, int opt)
|
|
{
|
|
return global_dc->warning_enabled_at (loc, opt);
|
|
}
|
|
|
|
inline bool
|
|
option_unspecified_p (int opt)
|
|
{
|
|
return global_dc->option_unspecified_p (opt);
|
|
}
|
|
|
|
extern char *get_cwe_url (int cwe);
|
|
|
|
#endif /* ! GCC_DIAGNOSTIC_H */
|