mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-21 19:35:36 -05:00
867 lines
25 KiB
C++
867 lines
25 KiB
C++
/* Language-independent diagnostic subroutines that implicitly use global_dc.
|
||
Copyright (C) 1999-2026 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/>. */
|
||
|
||
|
||
/* This file implements the parts of the language independent aspect
|
||
of diagnostic messages that implicitly use global_dc. */
|
||
|
||
#define INCLUDE_VECTOR
|
||
#include "config.h"
|
||
#include "system.h"
|
||
#include "coretypes.h"
|
||
#include "intl.h"
|
||
#include "diagnostic.h"
|
||
#include "diagnostics/sink.h"
|
||
#include "diagnostics/logging.h"
|
||
|
||
/* A diagnostics::context surrogate for stderr. */
|
||
static diagnostics::context global_diagnostic_context;
|
||
diagnostics::context *global_dc = &global_diagnostic_context;
|
||
|
||
using log_function_params = diagnostics::logging::log_function_params;
|
||
using auto_inc_log_depth = diagnostics::logging::auto_inc_depth;
|
||
|
||
/* Standard error reporting routines in increasing order of severity. */
|
||
|
||
/* Text to be emitted verbatim to the error message stream; this
|
||
produces no prefix and disables line-wrapping. Use rarely.
|
||
It is ignored for machine-readable output formats. */
|
||
void
|
||
verbatim (const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
text_info text (_(gmsgid), &ap, errno);
|
||
global_dc->report_verbatim (text);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Wrapper around diagnostics::context::diagnostic_impl
|
||
implying global_dc and taking a variable argument list. */
|
||
|
||
bool
|
||
emit_diagnostic (enum diagnostics::kind kind,
|
||
location_t location,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
|
||
gmsgid, &ap, kind);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("emit_diagnostic", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* As above, but for rich_location *. */
|
||
|
||
bool
|
||
emit_diagnostic (enum diagnostics::kind kind,
|
||
rich_location *richloc,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
|
||
gmsgid, &ap, kind);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("emit_diagnostic", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* As above, but taking a variable argument list. */
|
||
|
||
bool
|
||
emit_diagnostic_valist (enum diagnostics::kind kind,
|
||
location_t location,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, va_list *ap)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
|
||
gmsgid, ap, kind);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("emit_diagnostic_valist", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* As above, but with rich_location and metadata. */
|
||
|
||
bool
|
||
emit_diagnostic_valist_meta (enum diagnostics::kind kind,
|
||
rich_location *richloc,
|
||
const diagnostics::metadata *metadata,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, va_list *ap)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
bool ret = global_dc->diagnostic_impl (richloc, metadata, option_id,
|
||
gmsgid, ap, kind);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("emit_diagnostic_valist_meta", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* An informative note at LOCATION. Use this for additional details on an error
|
||
message. */
|
||
void
|
||
inform (location_t location, const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::note);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Same as "inform" above, but at RICHLOC. */
|
||
void
|
||
inform (rich_location *richloc, const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::note);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* An informative note at LOCATION. Use this for additional details on an
|
||
error message. */
|
||
void
|
||
inform_n (location_t location, unsigned HOST_WIDE_INT n,
|
||
const char *singular_gmsgid, const char *plural_gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
va_list ap;
|
||
va_start (ap, plural_gmsgid);
|
||
auto_diagnostic_group d;
|
||
rich_location richloc (line_table, location);
|
||
global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
|
||
singular_gmsgid, plural_gmsgid,
|
||
&ap, diagnostics::kind::note);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* A warning at INPUT_LOCATION. Use this for code which is correct according
|
||
to the relevant language specification but is likely to be buggy anyway.
|
||
Returns true if the warning was printed, false if it was inhibited. */
|
||
bool
|
||
warning (diagnostics::option_id option_id, const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, input_location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::warning);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("warning", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* A warning at LOCATION. Use this for code which is correct according to the
|
||
relevant language specification but is likely to be buggy anyway.
|
||
Returns true if the warning was printed, false if it was inhibited. */
|
||
|
||
bool
|
||
warning_at (location_t location,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::warning);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("warning_at", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Same as "warning at" above, but using RICHLOC. */
|
||
|
||
bool
|
||
warning_at (rich_location *richloc,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::warning);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("warning_at", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Same as "warning at" above, but using METADATA. */
|
||
|
||
bool
|
||
warning_meta (rich_location *richloc,
|
||
const diagnostics::metadata &metadata,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
bool ret = global_dc->diagnostic_impl (richloc, &metadata, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::warning);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("warning_meta", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Same as warning_n plural variant below, but using RICHLOC. */
|
||
|
||
bool
|
||
warning_n (rich_location *richloc,
|
||
diagnostics::option_id option_id,
|
||
unsigned HOST_WIDE_INT n,
|
||
const char *singular_gmsgid, const char *plural_gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, plural_gmsgid);
|
||
bool ret = global_dc->diagnostic_n_impl (richloc, nullptr, option_id, n,
|
||
singular_gmsgid, plural_gmsgid,
|
||
&ap, diagnostics::kind::warning);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("warning_n", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* A warning at LOCATION. Use this for code which is correct according to the
|
||
relevant language specification but is likely to be buggy anyway.
|
||
Returns true if the warning was printed, false if it was inhibited. */
|
||
|
||
bool
|
||
warning_n (location_t location,
|
||
diagnostics::option_id option_id,
|
||
unsigned HOST_WIDE_INT n,
|
||
const char *singular_gmsgid, const char *plural_gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, plural_gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_n_impl (&richloc, nullptr, option_id, n,
|
||
singular_gmsgid, plural_gmsgid,
|
||
&ap, diagnostics::kind::warning);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("warning_n", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* A "pedantic" warning at LOCATION: issues a warning unless
|
||
-pedantic-errors was given on the command line, in which case it
|
||
issues an error. Use this for diagnostics required by the relevant
|
||
language standard, if you have chosen not to make them errors.
|
||
|
||
Note that these diagnostics are issued independent of the setting
|
||
of the -Wpedantic command-line switch. To get a warning enabled
|
||
only with that switch, use either "if (pedantic) pedwarn
|
||
(OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
|
||
pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
|
||
|
||
Returns true if the warning was printed, false if it was inhibited. */
|
||
|
||
bool
|
||
pedwarn (location_t location,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::pedwarn);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("pedwarn", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Same as pedwarn above, but using RICHLOC. */
|
||
|
||
bool
|
||
pedwarn (rich_location *richloc,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::pedwarn);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("pedwarn", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* A "permissive" error at LOCATION: issues an error unless
|
||
-fpermissive was given on the command line, in which case it issues
|
||
a warning. Use this for things that really should be errors but we
|
||
want to support legacy code.
|
||
|
||
Returns true if the warning was printed, false if it was inhibited. */
|
||
|
||
bool
|
||
permerror (location_t location, const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::permerror);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("permerror", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Same as "permerror" above, but at RICHLOC. */
|
||
|
||
bool
|
||
permerror (rich_location *richloc, const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
bool ret = global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::permerror);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("permerror", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Similar to the above, but controlled by a flag other than -fpermissive.
|
||
As above, an error by default or a warning with -fpermissive, but this
|
||
diagnostic can also be downgraded by -Wno-error=opt. */
|
||
|
||
bool
|
||
permerror_opt (location_t location,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::permerror);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("permerror_opt", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* Same as "permerror" above, but at RICHLOC. */
|
||
|
||
bool
|
||
permerror_opt (rich_location *richloc,
|
||
diagnostics::option_id option_id,
|
||
const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_option_id ("option_id", option_id)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
|
||
gmsgid, &ap,
|
||
diagnostics::kind::permerror);
|
||
va_end (ap);
|
||
|
||
if (logger)
|
||
logger->log_bool_return ("permerror_opt", ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* A hard error: the code is definitely ill-formed, and an object file
|
||
will not be produced. */
|
||
void
|
||
error (const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, input_location);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::error);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* A hard error: the code is definitely ill-formed, and an object file
|
||
will not be produced. */
|
||
void
|
||
error_n (location_t location, unsigned HOST_WIDE_INT n,
|
||
const char *singular_gmsgid, const char *plural_gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("location", location)
|
||
.log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, plural_gmsgid);
|
||
rich_location richloc (line_table, location);
|
||
global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
|
||
singular_gmsgid, plural_gmsgid,
|
||
&ap, diagnostics::kind::error);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Same as above, but use location LOC instead of input_location. */
|
||
void
|
||
error_at (location_t loc, const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("loc", loc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, loc);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::error);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Same as above, but use RICH_LOC. */
|
||
|
||
void
|
||
error_at (rich_location *richloc, const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::error);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Same as above, but with metadata. */
|
||
|
||
void
|
||
error_meta (rich_location *richloc, const diagnostics::metadata &metadata,
|
||
const char *gmsgid, ...)
|
||
{
|
||
gcc_assert (richloc);
|
||
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_rich_location ("richloc", richloc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
global_dc->diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap,
|
||
diagnostics::kind::error);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* "Sorry, not implemented." Use for a language feature which is
|
||
required by the relevant specification but not implemented by GCC.
|
||
An object file will not be produced. */
|
||
void
|
||
sorry (const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, input_location);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::sorry);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Same as above, but use location LOC instead of input_location. */
|
||
void
|
||
sorry_at (location_t loc, const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("loc", loc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, loc);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::sorry);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* Return true if an error or a "sorry" has been seen on global_dc. Various
|
||
processing is disabled after errors. */
|
||
bool
|
||
seen_error (void)
|
||
{
|
||
return errorcount || sorrycount;
|
||
}
|
||
|
||
/* An error which is severe enough that we make no attempt to
|
||
continue. Do not use this for internal consistency checks; that's
|
||
internal_error. Use of this function should be rare. */
|
||
void
|
||
fatal_error (location_t loc, const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_location_t ("loc", loc)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, loc);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::fatal);
|
||
va_end (ap);
|
||
|
||
gcc_unreachable ();
|
||
}
|
||
|
||
/* An internal consistency check has failed. We make no attempt to
|
||
continue. */
|
||
void
|
||
internal_error (const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, input_location);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::ice);
|
||
va_end (ap);
|
||
|
||
gcc_unreachable ();
|
||
}
|
||
|
||
/* Like internal_error, but no backtrace will be printed. Used when
|
||
the internal error does not happen at the current location, but happened
|
||
somewhere else. */
|
||
void
|
||
internal_error_no_backtrace (const char *gmsgid, ...)
|
||
{
|
||
auto logger = global_dc->get_logger ();
|
||
log_function_params (logger, __func__)
|
||
.log_param_string ("gmsgid", gmsgid);
|
||
auto_inc_log_depth depth_sentinel (logger);
|
||
|
||
auto_diagnostic_group d;
|
||
va_list ap;
|
||
va_start (ap, gmsgid);
|
||
rich_location richloc (line_table, input_location);
|
||
global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
|
||
diagnostics::kind::ice_nobt);
|
||
va_end (ap);
|
||
|
||
gcc_unreachable ();
|
||
}
|
||
|
||
|
||
/* Special case error functions. Most are implemented in terms of the
|
||
above, or should be. */
|
||
|
||
/* Print a diagnostic MSGID on FILE. This is just fprintf, except it
|
||
runs its second argument through gettext. */
|
||
void
|
||
fnotice (FILE *file, const char *cmsgid, ...)
|
||
{
|
||
/* If the user requested one of the machine-readable diagnostic output
|
||
formats on stderr (e.g. -fdiagnostics-format=sarif-stderr), then
|
||
emitting free-form text on stderr will lead to corrupt output.
|
||
Skip the message for such cases. */
|
||
if (file == stderr && global_dc)
|
||
if (!global_dc->supports_fnotice_on_stderr_p ())
|
||
return;
|
||
|
||
va_list ap;
|
||
|
||
va_start (ap, cmsgid);
|
||
vfprintf (file, _(cmsgid), ap);
|
||
va_end (ap);
|
||
}
|
||
|
||
/* class auto_diagnostic_group. */
|
||
|
||
/* Constructor: "push" this group into global_dc. */
|
||
|
||
auto_diagnostic_group::auto_diagnostic_group ()
|
||
{
|
||
global_dc->begin_group ();
|
||
}
|
||
|
||
/* Destructor: "pop" this group from global_dc. */
|
||
|
||
auto_diagnostic_group::~auto_diagnostic_group ()
|
||
{
|
||
global_dc->end_group ();
|
||
}
|
||
|
||
/* class auto_diagnostic_nesting_level. */
|
||
|
||
auto_diagnostic_nesting_level::auto_diagnostic_nesting_level ()
|
||
{
|
||
global_dc->push_nesting_level ();
|
||
}
|
||
|
||
auto_diagnostic_nesting_level::~auto_diagnostic_nesting_level ()
|
||
{
|
||
global_dc->pop_nesting_level ();
|
||
}
|