aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS5
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/c-family/c-indentation.cc2
-rw-r--r--gcc/c-family/c-opts.cc2
-rw-r--r--gcc/common.opt12
-rw-r--r--gcc/common.opt.urls9
-rw-r--r--gcc/cp/error.cc4
-rw-r--r--gcc/diagnostic.h3
-rw-r--r--gcc/diagnostics/buffering.cc5
-rw-r--r--gcc/diagnostics/column-options.h44
-rw-r--r--gcc/diagnostics/context.cc124
-rw-r--r--gcc/diagnostics/context.h31
-rw-r--r--gcc/diagnostics/dumping.cc116
-rw-r--r--gcc/diagnostics/dumping.h43
-rw-r--r--gcc/diagnostics/file-cache.cc46
-rw-r--r--gcc/diagnostics/html-sink.cc40
-rw-r--r--gcc/diagnostics/html-sink.h2
-rw-r--r--gcc/diagnostics/metadata.h2
-rw-r--r--gcc/diagnostics/output-spec.cc14
-rw-r--r--gcc/diagnostics/sarif-sink.cc81
-rw-r--r--gcc/diagnostics/sarif-sink.h4
-rw-r--r--gcc/diagnostics/sink.h3
-rw-r--r--gcc/diagnostics/source-printing.cc8
-rw-r--r--gcc/diagnostics/text-sink.cc26
-rw-r--r--gcc/diagnostics/text-sink.h8
-rw-r--r--gcc/doc/invoke.texi56
-rw-r--r--gcc/lto-wrapper.cc9
-rw-r--r--gcc/opts-common.cc3
-rw-r--r--gcc/opts.cc22
-rw-r--r--gcc/testsuite/g++.dg/concepts/nested-diagnostics-1-truncated.C2
-rw-r--r--gcc/testsuite/g++.dg/concepts/nested-diagnostics-1.C2
-rw-r--r--gcc/testsuite/g++.dg/concepts/nested-diagnostics-2.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/noncall-eh-1.C26
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-no-show-nesting.c9
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-show-nesting.c24
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-show-levels.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-unicode.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp2
-rw-r--r--gcc/testsuite/gcc.dg/pr118946-1.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr121422-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr121422-2.c36
-rw-r--r--gcc/toplev.cc6
-rw-r--r--gcc/tree-diagnostic.cc2
-rw-r--r--gcc/tree-ssa-forwprop.cc421
-rw-r--r--libgcc/Makefile.in1
-rw-r--r--libgcc/config/aarch64/t-aarch642
-rwxr-xr-xlibgcc/configure19
-rw-r--r--libgcc/configure.ac14
-rw-r--r--libgcobol/libgcobol.cc70
-rw-r--r--libgcobol/stringbin.cc147
-rw-r--r--libgcobol/stringbin.h5
52 files changed, 1183 insertions, 388 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index bc607cb..dd31eed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,7 +276,7 @@ check in changes outside of the parts of the compiler they maintain.
Reviewers
aarch64 port Alex Coplan <alex.coplan@arm.com>
-aarch64 port Andrew Pinski <pinskia@gmail.com>
+aarch64 port Andrew Pinski <andrew.pinski@oss.qualcomm.com>
arm port (MVE) Christophe Lyon <christophe.lyon@arm.com>
callgraph Martin Jambor <mjambor@suse.cz>
C front end Marek Polacek <polacek@redhat.com>
@@ -734,7 +734,7 @@ Sebastian Peryt speryt <sebastian.peryt@intel.com>
Johannes Pfau jpfau <johannespfau@gmail.com>
Gerald Pfeifer gerald <gerald@pfeifer.com>
Kaushik Phatak kaushikp <kaushik.phatak@kpitcummins.com>
-Andrew Pinski pinskia <pinskia@gmail.com>
+Andrew Pinski pinskia <andrew.pinski@qualcomm.com>
Nicolas Pitre nico <nico@cam.org>
Michael Ploujnikov plouj <michael.ploujnikov@oracle.com>
Paul Pluzhnikov ppluzhnikov <ppluzhnikov@google.com>
@@ -959,6 +959,7 @@ Immad Mir <mir@sourceware.org>
Gaius Mulley <gaiusmod2@gmail.com>
Szabolcs Nagy <nsz@gcc.gnu.org>
Andrew Pinski <quic_apinski@quicinc.com>
+Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Siddhesh Poyarekar <siddhesh@gotplt.org>
Ramana Radhakrishnan <ramanara@nvidia.com>
Navid Rahimi <navidr@gcc.gnu.org>
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index cc79595..f21d692 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1856,6 +1856,7 @@ OBJS-libcommon = \
diagnostics/color.o \
diagnostics/context.o \
diagnostics/digraphs.o \
+ diagnostics/dumping.o \
diagnostics/file-cache.o \
diagnostics/output-spec.o \
diagnostics/html-sink.o \
diff --git a/gcc/c-family/c-indentation.cc b/gcc/c-family/c-indentation.cc
index bb214fc..d378464 100644
--- a/gcc/c-family/c-indentation.cc
+++ b/gcc/c-family/c-indentation.cc
@@ -330,7 +330,7 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
if (guard_loc == body_loc || body_loc == next_stmt_loc)
return false;
- const unsigned int tab_width = global_dc->m_tabstop;
+ const unsigned int tab_width = global_dc->get_column_options ().m_tabstop;
/* They must be in the same file. */
if (next_stmt_exploc.file != body_exploc.file)
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index 3fb12b9..0ec30e8 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -1200,7 +1200,7 @@ c_common_post_options (const char **pfilename)
flag_char8_t = (cxx_dialect >= cxx20) || flag_isoc23;
cpp_opts->unsigned_utf8char = flag_char8_t ? 1 : cpp_opts->unsigned_char;
- cpp_opts->cpp_tabstop = global_dc->m_tabstop;
+ cpp_opts->cpp_tabstop = global_dc->get_column_options ().m_tabstop;
if (flag_extern_tls_init)
{
diff --git a/gcc/common.opt b/gcc/common.opt
index bf38f60..c58ac13 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1620,6 +1620,18 @@ fdiagnostics-minimum-margin-width=
Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6)
Set minimum width of left margin of source code when showing source.
+fdiagnostics-show-nesting
+Common Var(flag_diagnostics_show_nesting) Init(1)
+Use indentation to show nesting of diagnostics in text output.
+
+fdiagnostics-show-nesting-locations
+Common Var(flag_diagnostics_show_nesting_locations) Init(1)
+Show location information when showing nested diagnostics.
+
+fdiagnostics-show-nesting-levels
+Common Var(flag_diagnostics_show_nesting_levels) Init(0)
+Show nesting levels as numbers when showing nested diagnostics.
+
fdisable-
Common Joined RejectNegative Var(common_deferred_options) Defer
-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 Disable an optimization pass.
diff --git a/gcc/common.opt.urls b/gcc/common.opt.urls
index 38dd9d3..0bc36c4 100644
--- a/gcc/common.opt.urls
+++ b/gcc/common.opt.urls
@@ -640,6 +640,15 @@ UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-text
fdiagnostics-minimum-margin-width=
UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-minimum-margin-width)
+fdiagnostics-show-nesting
+UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show-nesting)
+
+fdiagnostics-show-nesting-locations
+UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show-nesting-locations)
+
+fdiagnostics-show-nesting-levels
+UrlSuffix(gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-show-nesting-levels)
+
fdisable-
UrlSuffix(gcc/Developer-Options.html#index-fdisable-)
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index c427163..cd35c7a 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -250,7 +250,7 @@ erroneous_templates_t *erroneous_templates;
issue an error if we later need to instantiate the template. */
static void
-cp_adjust_diagnostic_info (diagnostics::context *context,
+cp_adjust_diagnostic_info (const diagnostics::context &context,
diagnostics::diagnostic_info *diagnostic)
{
if (diagnostic->m_kind == diagnostics::kind::error)
@@ -258,7 +258,7 @@ cp_adjust_diagnostic_info (diagnostics::context *context,
{
diagnostic->m_option_id = OPT_Wtemplate_body;
- if (context->m_permissive)
+ if (context.m_permissive)
diagnostic->m_kind = diagnostics::kind::warning;
bool existed;
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 7572e04..7d73046 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -277,9 +277,6 @@ namespace diagnostics {
/* Compute the number of digits in the decimal representation of an integer. */
extern int num_digits (int);
-extern char *get_cwe_url (int cwe);
-extern const char *maybe_line_and_column (int line, int col);
-
} // namespace diagnostics
#endif /* ! GCC_DIAGNOSTIC_H */
diff --git a/gcc/diagnostics/buffering.cc b/gcc/diagnostics/buffering.cc
index 29f039f..a7747b5 100644
--- a/gcc/diagnostics/buffering.cc
+++ b/gcc/diagnostics/buffering.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "diagnostics/buffering.h"
#include "diagnostics/sink.h"
+#include "diagnostics/dumping.h"
namespace diagnostics {
@@ -122,12 +123,12 @@ void
buffer::dump (FILE *out, int indent) const
{
m_diagnostic_counters.dump (out, indent + 2);
- fprintf (out, "%*sm_per_sink_buffers:\n", indent, "");
+ dumping::emit_heading (out, indent, "m_per_sink_buffers");
if (m_per_sink_buffers)
for (auto per_sink_buffer_ : *m_per_sink_buffers)
per_sink_buffer_->dump (out, indent + 2);
else
- fprintf (out, "%*s(none)\n", indent + 2, "");
+ dumping::emit_none (out, indent + 2);
}
bool
diff --git a/gcc/diagnostics/column-options.h b/gcc/diagnostics/column-options.h
new file mode 100644
index 0000000..86296e9
--- /dev/null
+++ b/gcc/diagnostics/column-options.h
@@ -0,0 +1,44 @@
+/* Options relating to the meaning of column numbers.
+ Copyright (C) 2000-2025 Free Software Foundation, Inc.
+
+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_DIAGNOSTICS_COLUMN_OPTIONS_H
+#define GCC_DIAGNOSTICS_COLUMN_OPTIONS_H
+
+namespace diagnostics {
+
+/* A bundle of options relating to the meaning of column numbers. */
+
+struct column_options
+{
+ int convert_column (file_cache &fc,
+ expanded_location s) const;
+
+ /* 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;
+};
+
+} // namespace diagnostics
+
+#endif /* ! GCC_DIAGNOSTICS_COLUMN_OPTIONS_H */
diff --git a/gcc/diagnostics/context.cc b/gcc/diagnostics/context.cc
index a1441ca..c948246 100644
--- a/gcc/diagnostics/context.cc
+++ b/gcc/diagnostics/context.cc
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostics/logical-locations.h"
#include "diagnostics/buffering.h"
#include "diagnostics/file-cache.h"
+#include "diagnostics/dumping.h"
#ifdef HAVE_TERMIOS_H
# include <termios.h>
@@ -176,12 +177,18 @@ context::initialize (int n_opts)
m_client_aux_data = nullptr;
m_lock = 0;
m_inhibit_notes_p = false;
+
m_source_printing.colorize_source_p = false;
m_source_printing.show_labels_p = false;
m_source_printing.show_line_numbers_p = false;
m_source_printing.min_margin_width = 0;
m_source_printing.show_ruler_p = false;
m_source_printing.show_event_links_p = false;
+
+ m_column_options.m_column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
+ m_column_options.m_column_origin = 1;
+ m_column_options.m_tabstop = 8;
+
m_report_bug = false;
m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
@@ -192,9 +199,6 @@ context::initialize (int n_opts)
m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
/* Silently ignore unrecognized values. */
}
- m_column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
- m_column_origin = 1;
- m_tabstop = 8;
m_escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
m_fixits_change_set = nullptr;
m_diagnostic_groups.m_group_nesting_depth = 0;
@@ -284,6 +288,33 @@ context::urls_init (int value)
(m_reference_printer->get_url_format ());
}
+void
+context::set_show_nesting (bool val)
+{
+ for (auto sink_ : m_sinks)
+ if (sink_->follows_reference_printer_p ())
+ if (auto text_sink_ = sink_->dyn_cast_text_sink ())
+ text_sink_->set_show_nesting (val);
+}
+
+void
+context::set_show_nesting_locations (bool val)
+{
+ for (auto sink_ : m_sinks)
+ if (sink_->follows_reference_printer_p ())
+ if (auto text_sink_ = sink_->dyn_cast_text_sink ())
+ text_sink_->set_show_locations_in_nesting (val);
+}
+
+void
+context::set_show_nesting_levels (bool val)
+{
+ for (auto sink_ : m_sinks)
+ if (sink_->follows_reference_printer_p ())
+ if (auto text_sink_ = sink_->dyn_cast_text_sink ())
+ text_sink_->set_show_nesting_levels (val);
+}
+
/* Create the file_cache, if not already created, and tell it how to
translate files on input. */
void
@@ -355,33 +386,37 @@ context::finish ()
/* Dump state of this diagnostics::context to OUT, for debugging. */
void
-context::dump (FILE *out) const
+context::dump (FILE *outfile) const
{
- fprintf (out, "diagnostics::context:\n");
- m_diagnostic_counters.dump (out, 2);
- fprintf (out, " reference printer:\n");
- m_reference_printer->dump (out, 4);
- fprintf (out, " output sinks:\n");
+ dumping::emit_heading (outfile, 0, "diagnostics::context");
+ m_diagnostic_counters.dump (outfile, 2);
+ dumping::emit_heading (outfile, 2, "reference printer");
+ m_reference_printer->dump (outfile, 4);
+ dumping::emit_heading (outfile, 2, "output sinks");
if (m_sinks.length () > 0)
{
for (unsigned i = 0; i < m_sinks.length (); ++i)
{
- fprintf (out, " sink %i:\n", i);
- m_sinks[i]->dump (out, 4);
+ dumping::emit_indent (outfile, 4);
+ const sink *s = m_sinks[i];
+ fprintf (outfile, "sink %i (", i);
+ s->dump_kind (outfile);
+ fprintf (outfile, "):\n");
+ s->dump (outfile, 6);
}
}
else
- fprintf (out, " (none):\n");
- fprintf (out, " diagnostic buffer:\n");
+ dumping::emit_none (outfile, 4);
+ dumping::emit_heading (outfile, 2, "diagnostic buffer");
if (m_diagnostic_buffer)
- m_diagnostic_buffer->dump (out, 4);
+ m_diagnostic_buffer->dump (outfile, 4);
else
- fprintf (out, " (none):\n");
- fprintf (out, " file cache:\n");
+ dumping::emit_none (outfile, 4);
+ dumping::emit_heading (outfile, 2, "file cache");
if (m_file_cache)
- m_file_cache->dump (out, 4);
+ m_file_cache->dump (outfile, 4);
else
- fprintf (out, " (none):\n");
+ dumping::emit_none (outfile, 4);
}
/* Return true if sufficiently severe diagnostics have been seen that
@@ -671,11 +706,22 @@ convert_column_unit (file_cache &fc,
}
}
+/* Given an expanded_location, convert the column (which is in 1-based bytes)
+ to the requested units and origin. Return -1 if the column is
+ invalid (<= 0). */
+int
+column_options::convert_column (file_cache &fc,
+ expanded_location s) const
+{
+ int one_based_col = convert_column_unit (fc, m_column_unit, m_tabstop, s);
+ if (one_based_col <= 0)
+ return -1;
+ return one_based_col + (m_column_origin - 1);
+}
+
column_policy::column_policy (const context &dc)
: m_file_cache (dc.get_file_cache ()),
- m_column_unit (dc.m_column_unit),
- m_column_origin (dc.m_column_origin),
- m_tabstop (dc.m_tabstop)
+ m_column_options (dc.get_column_options ())
{
}
@@ -685,11 +731,7 @@ column_policy::column_policy (const context &dc)
int
column_policy::converted_column (expanded_location s) const
{
- int one_based_col = convert_column_unit (m_file_cache,
- m_column_unit, m_tabstop, s);
- if (one_based_col <= 0)
- return -1;
- return one_based_col + (m_column_origin - 1);
+ return m_column_options.convert_column (m_file_cache, s);
}
/* Return a string describing a location e.g. "foo.c:42:10". */
@@ -711,7 +753,7 @@ column_policy::get_location_text (const expanded_location &s,
col = converted_column (s);
}
- const char *line_col = maybe_line_and_column (line, col);
+ const char *line_col = text_sink::maybe_line_and_column (line, col);
return label_text::take (build_message_string ("%s%s%s:%s", locus_cs, file,
line_col, locus_ce));
}
@@ -1098,7 +1140,7 @@ context::get_any_inlining_info (diagnostic_info *diagnostic)
/* Retrieve the locations into which the expression about to be
diagnosed has been inlined, including those of all the callers
all the way down the inlining stack. */
- m_set_locations_cb (this, diagnostic);
+ m_set_locations_cb (*this, diagnostic);
else
{
/* When there's no callback use just the one location provided
@@ -1249,7 +1291,7 @@ context::report_diagnostic (diagnostic_info *diagnostic)
}
if (m_adjust_diagnostic_info)
- m_adjust_diagnostic_info (this, diagnostic);
+ m_adjust_diagnostic_info (*this, diagnostic);
if (diagnostic->m_kind == kind::pedwarn)
{
@@ -1385,6 +1427,8 @@ context::report_diagnostic (diagnostic_info *diagnostic)
sink_->on_report_diagnostic (*diagnostic, orig_diag_kind);
}
+ const int tabstop = get_column_options ().m_tabstop;
+
switch (m_extra_output_kind)
{
default:
@@ -1393,14 +1437,14 @@ context::report_diagnostic (diagnostic_info *diagnostic)
print_parseable_fixits (get_file_cache (),
m_reference_printer, diagnostic->m_richloc,
DIAGNOSTICS_COLUMN_UNIT_BYTE,
- m_tabstop);
+ tabstop);
pp_flush (m_reference_printer);
break;
case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
print_parseable_fixits (get_file_cache (),
m_reference_printer, diagnostic->m_richloc,
DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
- m_tabstop);
+ tabstop);
pp_flush (m_reference_printer);
break;
}
@@ -1690,7 +1734,7 @@ context::set_nesting_level (int new_level)
void
sink::dump (FILE *out, int indent) const
{
- fprintf (out, "%*sprinter:\n", indent, "");
+ dumping::emit_heading (out, indent, "printer");
m_printer->dump (out, indent + 2);
}
@@ -1777,19 +1821,19 @@ counters::counters ()
void
counters::dump (FILE *out, int indent) const
{
- fprintf (out, "%*scounts:\n", indent, "");
+ dumping::emit_heading (out, indent, "counts");
bool none = true;
for (int i = 0; i < static_cast<int> (kind::last_diagnostic_kind); i++)
if (m_count_for_kind[i] > 0)
{
- fprintf (out, "%*s%s%i\n",
- indent + 2, "",
+ dumping::emit_indent (out, indent + 2);
+ fprintf (out, "%s%i\n",
get_text_for_kind (static_cast<enum kind> (i)),
m_count_for_kind[i]);
none = false;
}
if (none)
- fprintf (out, "%*s(none)\n", indent + 2, "");
+ dumping::emit_none (out, indent + 2);
}
void
@@ -2015,8 +2059,8 @@ assert_location_text (const char *expected_loc_text,
= DIAGNOSTICS_COLUMN_UNIT_BYTE)
{
diagnostics::selftest::test_context dc;
- dc.m_column_unit = column_unit;
- dc.m_column_origin = origin;
+ dc.get_column_options ().m_column_unit = column_unit;
+ dc.get_column_options ().m_column_origin = origin;
expanded_location xloc;
xloc.file = filename;
@@ -2052,8 +2096,8 @@ test_get_location_text ()
assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
assert_location_text ("foo.c:", "foo.c", 0, 10, false);
- diagnostics::maybe_line_and_column (INT_MAX, INT_MAX);
- diagnostics::maybe_line_and_column (INT_MIN, INT_MIN);
+ diagnostics::text_sink::maybe_line_and_column (INT_MAX, INT_MAX);
+ diagnostics::text_sink::maybe_line_and_column (INT_MIN, INT_MIN);
{
/* In order to test display columns vs byte columns, we need to create a
diff --git a/gcc/diagnostics/context.h b/gcc/diagnostics/context.h
index b6ec85c..dea4588 100644
--- a/gcc/diagnostics/context.h
+++ b/gcc/diagnostics/context.h
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostics/option-id-manager.h"
#include "diagnostics/context-options.h"
#include "diagnostics/source-printing-options.h"
+#include "diagnostics/column-options.h"
#include "diagnostics/counters.h"
namespace diagnostics {
@@ -99,13 +100,11 @@ public:
bool show_column,
bool colorize) const;
- int get_tabstop () const { return m_tabstop; }
+ int get_tabstop () const { return m_column_options.m_tabstop; }
private:
file_cache &m_file_cache;
- enum diagnostics_column_unit m_column_unit;
- int m_column_origin;
- int m_tabstop;
+ column_options m_column_options;
};
/* A bundle of state for printing locations within diagnostics
@@ -265,7 +264,7 @@ public:
friend class text_sink;
friend class buffer;
- typedef void (*set_locations_callback_t) (context *,
+ typedef void (*set_locations_callback_t) (const context &,
diagnostic_info *);
void initialize (int n_opts);
@@ -393,6 +392,9 @@ public:
}
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_show_nesting (bool val);
+ void set_show_nesting_locations (bool val);
+ void set_show_nesting_levels (bool val);
void set_max_errors (int val) { m_max_errors = val; }
void set_escape_format (enum diagnostics_escape_format val)
{
@@ -572,7 +574,7 @@ public:
}
void
- set_adjust_diagnostic_info_callback (void (*cb) (context *,
+ set_adjust_diagnostic_info_callback (void (*cb) (const context &,
diagnostic_info *))
{
m_adjust_diagnostic_info = cb;
@@ -592,6 +594,9 @@ public:
return m_source_printing;
}
+ column_options &get_column_options () { return m_column_options; }
+ const column_options &get_column_options () const { return m_column_options; }
+
void set_caret_max_width (int value);
private:
@@ -708,7 +713,7 @@ private:
/* Client hook to adjust properties of the given diagnostic that we're
about to issue, such as its kind. */
- void (*m_adjust_diagnostic_info)(context *, diagnostic_info *);
+ void (*m_adjust_diagnostic_info)(const context &, diagnostic_info *);
/* Owned by the context; this would be a std::unique_ptr if
context had a proper ctor. */
@@ -739,6 +744,7 @@ private:
bool m_inhibit_notes_p;
source_printing_options m_source_printing;
+ column_options m_column_options;
/* True if -freport-bug option is used. */
bool m_report_bug;
@@ -748,17 +754,6 @@ private:
-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;
diff --git a/gcc/diagnostics/dumping.cc b/gcc/diagnostics/dumping.cc
new file mode 100644
index 0000000..f0366a5
--- /dev/null
+++ b/gcc/diagnostics/dumping.cc
@@ -0,0 +1,116 @@
+/* Utilities for implementing "dump" functions for the diagnostics subsystem.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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/>. */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostics/dumping.h"
+
+namespace diagnostics {
+namespace dumping {
+
+/* Emit indentation to OUTFILE for the start of a dump line. */
+
+void
+emit_indent (FILE *outfile, int indent)
+{
+ fprintf (outfile, "%*s", indent, "");
+}
+
+/* Emit an indented line to OUTFILE showing a heading. */
+
+void
+emit_heading (FILE *outfile, int indent,
+ const char *text)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "%s:\n", text);
+}
+
+/* Various specializattions that emit an indented line to OUTFILE
+ showing "label: value". */
+
+template <>
+void
+emit_field<const char *> (FILE *outfile, int indent,
+ const char *label, const char *value)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "%s: %s\n", label, value);
+}
+
+template <>
+void
+emit_field<char *> (FILE *outfile, int indent,
+ const char *label, char *value)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "%s: %s\n", label, value);
+}
+
+template <>
+void
+emit_field<bool> (FILE *outfile, int indent,
+ const char *label, bool value)
+{
+ emit_field<const char *> (outfile, indent, label,
+ value ? "true" : "false");
+}
+
+template <>
+void
+emit_field<size_t> (FILE *outfile, int indent,
+ const char *label, size_t value)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "%s: %zi\n", label, value);
+}
+
+template <>
+void
+emit_field<int> (FILE *outfile, int indent,
+ const char *label, int value)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "%s: %i\n", label, value);
+}
+
+template <>
+void
+emit_field<unsigned> (FILE *outfile, int indent,
+ const char *label, unsigned value)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "%s: %u\n", label, value);
+}
+
+/* Emit an indented line to OUTFILE reading "(none)". */
+
+void
+emit_none (FILE *outfile, int indent)
+{
+ emit_indent (outfile, indent);
+ fprintf (outfile, "(none)\n");
+}
+
+
+} // namespace dumping {
+} // namespace diagnostics
diff --git a/gcc/diagnostics/dumping.h b/gcc/diagnostics/dumping.h
new file mode 100644
index 0000000..08c7ee4
--- /dev/null
+++ b/gcc/diagnostics/dumping.h
@@ -0,0 +1,43 @@
+/* Utilities for implementing "dump" functions for the diagnostics subsystem.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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_DIAGNOSTICS_DUMP_H
+#define GCC_DIAGNOSTICS_DUMP_H
+
+namespace diagnostics {
+namespace dumping {
+
+extern void emit_indent (FILE *outfile, int indent);
+extern void emit_heading (FILE *outfile, int indent,
+ const char *text);
+
+template <typename T>
+extern void emit_field (FILE *outfile, int indent,
+ const char *label, T value);
+
+extern void emit_none (FILE *outfile, int indent);
+
+#define DIAGNOSTICS_DUMPING_EMIT_FIELD(FLAG) \
+ dumping::emit_field (outfile, indent, #FLAG, FLAG)
+
+} // namespace dumping
+} // namespace diagnostics
+
+#endif /* ! GCC_DIAGNOSTICS_DUMP_H */
diff --git a/gcc/diagnostics/file-cache.cc b/gcc/diagnostics/file-cache.cc
index febeb03..9acf82e 100644
--- a/gcc/diagnostics/file-cache.cc
+++ b/gcc/diagnostics/file-cache.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "cpplib.h"
#include "diagnostics/file-cache.h"
+#include "diagnostics/dumping.h"
#include "selftest.h"
#ifndef HAVE_ICONV
@@ -473,7 +474,8 @@ file_cache::dump (FILE *out, int indent) const
{
for (size_t i = 0; i < m_num_file_slots; ++i)
{
- fprintf (out, "%*sslot[%i]:\n", indent, "", (int)i);
+ dumping::emit_indent (out, indent);
+ fprintf (out, "slot[%i]:\n", (int)i);
m_file_slots[i].dump (out, indent + 2);
}
}
@@ -541,27 +543,35 @@ file_cache_slot::dump (FILE *out, int indent) const
{
if (!m_file_path)
{
- fprintf (out, "%*s(unused)\n", indent, "");
+ dumping::emit_indent (out, indent);
+ fprintf (out, "(unused)\n");
return;
}
- fprintf (out, "%*sfile_path: %s\n", indent, "", m_file_path);
- fprintf (out, "%*sfp: %p\n", indent, "", (void *)m_fp);
- fprintf (out, "%*sneeds_read_p: %i\n", indent, "", (int)needs_read_p ());
- fprintf (out, "%*sneeds_grow_p: %i\n", indent, "", (int)needs_grow_p ());
- fprintf (out, "%*suse_count: %i\n", indent, "", m_use_count);
- fprintf (out, "%*ssize: %zi\n", indent, "", m_size);
- fprintf (out, "%*snb_read: %zi\n", indent, "", m_nb_read);
- fprintf (out, "%*sstart_line_idx: %zi\n", indent, "", m_line_start_idx);
- fprintf (out, "%*sline_num: %zi\n", indent, "", m_line_num);
- fprintf (out, "%*smissing_trailing_newline: %i\n",
- indent, "", (int)m_missing_trailing_newline);
- fprintf (out, "%*sline records (%i):\n",
- indent, "", m_line_record.length ());
+ dumping::emit_field (out, indent, "file_path", m_file_path);
+ {
+ dumping::emit_indent (out, indent);
+ fprintf (out, "fp: %p\n", (void *)m_fp);
+ }
+ dumping::emit_field (out, indent, "needs_read_p", needs_read_p ());
+ dumping::emit_field (out, indent, "needs_grow_p", needs_grow_p ());
+ dumping::emit_field (out, indent, "use_count", m_use_count);
+ dumping::emit_field (out, indent, "size", m_size);
+ dumping::emit_field (out, indent, "nb_read", m_nb_read);
+ dumping::emit_field (out, indent, "start_line_idx", m_line_start_idx);
+ dumping::emit_field (out, indent, "line_num", m_line_num);
+ dumping::emit_field (out, indent, "missing_trailing_newline",
+ (int)m_missing_trailing_newline);
+ {
+ dumping::emit_indent (out, indent);
+ fprintf (out, "line records (%i):\n", m_line_record.length ());
+ }
int idx = 0;
for (auto &line : m_line_record)
- fprintf (out, "%*s[%i]: line %zi: byte offsets: %zi-%zi\n",
- indent + 2, "",
- idx++, line.line_num, line.start_pos, line.end_pos);
+ {
+ dumping::emit_indent (out, indent);
+ fprintf (out, "[%i]: line %zi: byte offsets: %zi-%zi\n",
+ idx++, line.line_num, line.start_pos, line.end_pos);
+ }
}
/* Returns TRUE iff the cache would need to be filled with data coming
diff --git a/gcc/diagnostics/html-sink.cc b/gcc/diagnostics/html-sink.cc
index 934d8e2..448d461 100644
--- a/gcc/diagnostics/html-sink.cc
+++ b/gcc/diagnostics/html-sink.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostics/output-file.h"
#include "diagnostics/buffering.h"
#include "diagnostics/paths.h"
+#include "diagnostics/dumping.h"
#include "diagnostics/client-data-hooks.h"
#include "selftest.h"
#include "diagnostics/selftest-context.h"
@@ -61,6 +62,16 @@ html_generation_options::html_generation_options ()
{
}
+void
+html_generation_options::dump (FILE *outfile, int indent) const
+{
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_css);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_javascript);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_show_state_diagrams);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_show_state_diagrams_sarif);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_show_state_diagrams_dot_src);
+}
+
class html_builder;
/* Concrete buffering implementation subclass for HTML output. */
@@ -116,6 +127,8 @@ public:
const line_maps *line_maps,
const html_generation_options &html_gen_opts);
+ void dump (FILE *out, int indent) const;
+
void
set_main_input_filename (const char *name);
@@ -223,11 +236,12 @@ make_span (std::string class_)
void
html_sink_buffer::dump (FILE *out, int indent) const
{
- fprintf (out, "%*shtml_sink_buffer:\n", indent, "");
+ dumping::emit_heading (out, indent, "html_sink_buffer");
int idx = 0;
for (auto &result : m_results)
{
- fprintf (out, "%*sresult[%i]:\n", indent + 2, "", idx);
+ dumping::emit_indent (out, indent + 2);
+ fprintf (out, "result[%i]:\n", idx);
result->dump (out);
fprintf (out, "\n");
++idx;
@@ -470,6 +484,13 @@ html_builder::html_builder (context &dc,
}
void
+html_builder::dump (FILE *out, int indent) const
+{
+ dumping::emit_heading (out, indent, "HTML generation options");
+ m_html_gen_opts.dump (out, indent + 2);
+}
+
+void
html_builder::set_main_input_filename (const char *name)
{
gcc_assert (m_title_element);
@@ -539,7 +560,7 @@ html_builder::on_report_diagnostic (const diagnostic_info &diagnostic,
}
}
-// For ease of comparison with experimental-nesting-show-levels=yes
+// For ease of comparison with show-nesting-levels=yes
static void
add_nesting_level_attr (xml::element &element,
@@ -1333,8 +1354,9 @@ public:
void dump (FILE *out, int indent) const override
{
- fprintf (out, "%*shtml_sink\n", indent, "");
sink::dump (out, indent);
+ dumping::emit_heading (out, indent, "html_builder");
+ m_builder.dump (out, indent + 2);
}
void
@@ -1439,12 +1461,10 @@ public:
{
m_builder.flush_to_file (m_output_file.get_open_file ());
}
- void dump (FILE *out, int indent) const override
+ void dump_kind (FILE *out) const override
{
- fprintf (out, "%*shtml_file_sink: %s\n",
- indent, "",
+ fprintf (out, "html_file_sink: %s",
m_output_file.get_filename ());
- sink::dump (out, indent);
}
bool machine_readable_stderr_p () const final override
{
@@ -1607,6 +1627,10 @@ private:
: html_sink (dc, line_maps, html_gen_opts)
{
}
+ void dump_kind (FILE *out) const final override
+ {
+ fprintf (out, "html_buffered_sink");
+ }
bool machine_readable_stderr_p () const final override
{
return true;
diff --git a/gcc/diagnostics/html-sink.h b/gcc/diagnostics/html-sink.h
index d86bde8..d25ceea 100644
--- a/gcc/diagnostics/html-sink.h
+++ b/gcc/diagnostics/html-sink.h
@@ -30,6 +30,8 @@ struct html_generation_options
{
html_generation_options ();
+ void dump (FILE *out, int indent) const;
+
bool m_css;
bool m_javascript;
diff --git a/gcc/diagnostics/metadata.h b/gcc/diagnostics/metadata.h
index c28f982..39291ec 100644
--- a/gcc/diagnostics/metadata.h
+++ b/gcc/diagnostics/metadata.h
@@ -119,6 +119,8 @@ class metadata
const lazy_digraphs *m_lazy_digraphs;
};
+extern char *get_cwe_url (int cwe);
+
} // namespace diagnostics
#endif /* ! GCC_DIAGNOSTICS_METADATA_H */
diff --git a/gcc/diagnostics/output-spec.cc b/gcc/diagnostics/output-spec.cc
index 83f128c..13565f9 100644
--- a/gcc/diagnostics/output-spec.cc
+++ b/gcc/diagnostics/output-spec.cc
@@ -368,7 +368,7 @@ text_scheme_handler::make_sink (const context &ctxt,
const scheme_name_and_params &parsed_arg) const
{
bool show_color = pp_show_color (dc.get_reference_printer ());
- bool show_nesting = false;
+ bool show_nesting = true;
bool show_locations_in_nesting = true;
bool show_levels = false;
for (auto& iter : parsed_arg.m_kvs)
@@ -381,21 +381,21 @@ text_scheme_handler::make_sink (const context &ctxt,
return nullptr;
continue;
}
- if (key == "experimental-nesting")
+ if (key == "show-nesting")
{
if (!parse_bool_value (ctxt, unparsed_arg, key, value,
show_nesting))
return nullptr;
continue;
}
- if (key == "experimental-nesting-show-locations")
+ if (key == "show-nesting-locations")
{
if (!parse_bool_value (ctxt, unparsed_arg, key, value,
show_locations_in_nesting))
return nullptr;
continue;
}
- if (key == "experimental-nesting-show-levels")
+ if (key == "show-nesting-levels")
{
if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_levels))
return nullptr;
@@ -405,9 +405,9 @@ text_scheme_handler::make_sink (const context &ctxt,
/* Key not found. */
auto_vec<const char *> known_keys;
known_keys.safe_push ("color");
- known_keys.safe_push ("experimental-nesting");
- known_keys.safe_push ("experimental-nesting-show-locations");
- known_keys.safe_push ("experimental-nesting-show-levels");
+ known_keys.safe_push ("show-nesting");
+ known_keys.safe_push ("show-nesting-locations");
+ known_keys.safe_push ("show-nesting-levels");
ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
known_keys);
return nullptr;
diff --git a/gcc/diagnostics/sarif-sink.cc b/gcc/diagnostics/sarif-sink.cc
index 4738ae9..0c4d77a 100644
--- a/gcc/diagnostics/sarif-sink.cc
+++ b/gcc/diagnostics/sarif-sink.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostics/paths.h"
#include "diagnostics/sink.h"
#include "diagnostics/buffering.h"
+#include "diagnostics/dumping.h"
#include "json.h"
#include "cpplib.h"
#include "diagnostics/logical-locations.h"
@@ -704,6 +705,14 @@ sarif_serialization_format_json::write_to_file (FILE *outf,
fprintf (outf, "\n");
}
+void
+sarif_serialization_format_json::dump (FILE *outfile, int indent) const
+{
+ dumping::emit_indent (outfile, indent);
+ fprintf (outfile, "json\n");
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_formatted);
+}
+
/* A class for managing SARIF output (for -fdiagnostics-format=sarif-stderr
and -fdiagnostics-format=sarif-file).
@@ -760,6 +769,8 @@ public:
const sarif_generation_options &sarif_gen_opts);
~sarif_builder ();
+ void dump (FILE *out, int indent) const;
+
void set_printer (pretty_printer &printer)
{
m_printer = &printer;
@@ -1674,7 +1685,7 @@ sarif_builder::sarif_builder (diagnostics::context &dc,
(std::make_unique<sarif_array_of_unique<sarif_logical_location>> ()),
m_run_graphs
(std::make_unique<sarif_array_of_unique<sarif_graph>> ()),
- m_tabstop (dc.m_tabstop),
+ m_tabstop (dc.get_column_options ().m_tabstop),
m_serialization_format (std::move (serialization_format)),
m_sarif_gen_opts (sarif_gen_opts),
m_next_result_idx (0),
@@ -1699,6 +1710,15 @@ sarif_builder::~sarif_builder ()
}
}
+void
+sarif_builder::dump (FILE *out, int indent) const
+{
+ dumping::emit_heading (out, indent, "serialization format");
+ m_serialization_format->dump (out, indent + 2);
+ dumping::emit_heading (out, indent, "SARIF generation options");
+ m_sarif_gen_opts.dump (out, indent + 2);
+}
+
/* Functions at which to stop the backtrace print. It's not
particularly helpful to print the callers of these functions. */
@@ -3803,11 +3823,12 @@ sarif_builder::make_artifact_content_object (const char *text) const
void
sarif_sink_buffer::dump (FILE *out, int indent) const
{
- fprintf (out, "%*ssarif_sink_buffer:\n", indent, "");
+ dumping::emit_heading (out, indent, "sarif_sink_buffer");
int idx = 0;
for (auto &result : m_results)
{
- fprintf (out, "%*sresult[%i]:\n", indent + 2, "", idx);
+ dumping::emit_indent (out, indent + 2);
+ fprintf (out, "result[%i]:\n", idx);
result->dump (out, true);
fprintf (out, "\n");
++idx;
@@ -3862,8 +3883,9 @@ public:
void dump (FILE *out, int indent) const override
{
- fprintf (out, "%*ssarif_sink\n", indent, "");
sink::dump (out, indent);
+ dumping::emit_heading (out, indent, "sarif_builder");
+ m_builder.dump (out, indent + 2);
}
void
@@ -3973,6 +3995,10 @@ public:
{
m_builder.flush_to_file (m_stream);
}
+ void dump_kind (FILE *out) const override
+ {
+ fprintf (out, "sarif_stream_sink");
+ }
bool machine_readable_stderr_p () const final override
{
return m_stream == stderr;
@@ -4001,12 +4027,10 @@ public:
{
m_builder.flush_to_file (m_output_file.get_open_file ());
}
- void dump (FILE *out, int indent) const override
+ void dump_kind (FILE *out) const override
{
- fprintf (out, "%*ssarif_file_sink: %s\n",
- indent, "",
+ fprintf (out, "sarif_file_sink: %s",
m_output_file.get_filename ());
- sink::dump (out, indent);
}
bool machine_readable_stderr_p () const final override
{
@@ -4319,6 +4343,29 @@ sarif_generation_options::sarif_generation_options ()
{
}
+static const char *
+get_dump_string_for_sarif_version (enum sarif_version version)
+{
+ switch (version)
+ {
+ default:
+ gcc_unreachable ();
+ case sarif_version::v2_1_0:
+ return "v2_1_0";
+ case sarif_version::v2_2_prerelease_2024_08_08:
+ return "v2_2_prerelease_2024_08_08";
+ }
+}
+
+void
+sarif_generation_options::dump (FILE *outfile, int indent) const
+{
+ dumping::emit_field (outfile, indent,
+ "m_version",
+ get_dump_string_for_sarif_version (m_version));
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_state_graph);
+}
+
#if CHECKING_P
namespace selftest {
@@ -4406,10 +4453,10 @@ public:
test_sarif_diagnostic_context (const char *main_input_filename,
const sarif_generation_options &sarif_gen_opts)
{
- auto sink_ = std::make_unique<buffered_sink> (*this,
- line_table,
- true,
- sarif_gen_opts);
+ auto sink_ = std::make_unique<sarif_buffered_sink> (*this,
+ line_table,
+ true,
+ sarif_gen_opts);
m_sink = sink_.get (); // borrowed
init_sarif_sink (*this, std::move (sink_));
m_sink->set_main_input_filename (main_input_filename);
@@ -4424,10 +4471,10 @@ public:
sarif_result &get_result (size_t idx) { return m_sink->get_result (idx); }
private:
- class buffered_sink : public sarif_sink
+ class sarif_buffered_sink : public sarif_sink
{
public:
- buffered_sink (context &dc,
+ sarif_buffered_sink (context &dc,
const line_maps *line_maps,
bool formatted,
const sarif_generation_options &sarif_gen_opts)
@@ -4436,6 +4483,10 @@ private:
sarif_gen_opts)
{
}
+ void dump_kind (FILE *out) const final override
+ {
+ fprintf (out, "sarif_buffered_sink");
+ }
bool machine_readable_stderr_p () const final override
{
return false;
@@ -4446,7 +4497,7 @@ private:
}
};
- buffered_sink *m_sink; // borrowed
+ sarif_buffered_sink *m_sink; // borrowed
};
/* Test making a sarif_location for a complex rich_location
diff --git a/gcc/diagnostics/sarif-sink.h b/gcc/diagnostics/sarif-sink.h
index 9f8a73f..e6f897b 100644
--- a/gcc/diagnostics/sarif-sink.h
+++ b/gcc/diagnostics/sarif-sink.h
@@ -73,6 +73,7 @@ public:
virtual ~sarif_serialization_format () {}
virtual void write_to_file (FILE *outf,
const json::value &top) = 0;
+ virtual void dump (FILE *out, int indent) const = 0;
};
/* Concrete subclass for serializing SARIF as JSON. */
@@ -85,6 +86,7 @@ public:
{
}
void write_to_file (FILE *outf, const json::value &top) final override;
+ void dump (FILE *out, int indent) const final override;
private:
bool m_formatted;
@@ -108,6 +110,8 @@ struct sarif_generation_options
{
sarif_generation_options ();
+ void dump (FILE *out, int indent) const;
+
enum sarif_version m_version;
bool m_state_graph;
};
diff --git a/gcc/diagnostics/sink.h b/gcc/diagnostics/sink.h
index ac4e0fb64..24eb707 100644
--- a/gcc/diagnostics/sink.h
+++ b/gcc/diagnostics/sink.h
@@ -36,6 +36,9 @@ class sink
public:
virtual ~sink () {}
+ virtual text_sink *dyn_cast_text_sink () { return nullptr; }
+
+ virtual void dump_kind (FILE *out) const = 0;
virtual void dump (FILE *out, int indent) const;
/* Vfunc for notifying this format what the primary input file is,
diff --git a/gcc/diagnostics/source-printing.cc b/gcc/diagnostics/source-printing.cc
index 94b1c2d..aeda9ad 100644
--- a/gcc/diagnostics/source-printing.cc
+++ b/gcc/diagnostics/source-printing.cc
@@ -4412,7 +4412,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
{
test_context dc;
- dc.m_tabstop = tabstop;
+ dc.get_column_options ().m_tabstop = tabstop;
diagnostics::source_print_policy policy (dc);
layout test_layout (policy, richloc, nullptr);
colorizer col (*dc.get_reference_printer (),
@@ -4436,7 +4436,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
{
test_context dc;
- dc.m_tabstop = tabstop;
+ dc.get_column_options ().m_tabstop = tabstop;
static const int small_width = 24;
auto &source_printing_opts = dc.get_source_printing_options ();
source_printing_opts.max_width = small_width - 4;
@@ -6833,7 +6833,7 @@ test_tab_expansion (const line_table_case &case_)
everything too. */
{
test_context dc;
- dc.m_tabstop = tabstop;
+ dc.get_column_options ().m_tabstop = tabstop;
rich_location richloc (line_table,
linemap_position_for_column (line_table,
first_non_ws_byte_col));
@@ -6846,7 +6846,7 @@ test_tab_expansion (const line_table_case &case_)
as well. */
{
test_context dc;
- dc.m_tabstop = tabstop;
+ dc.get_column_options ().m_tabstop = tabstop;
rich_location richloc (line_table,
linemap_position_for_column (line_table,
right_quote_byte_col));
diff --git a/gcc/diagnostics/text-sink.cc b/gcc/diagnostics/text-sink.cc
index bcf91cf..a7ebb30 100644
--- a/gcc/diagnostics/text-sink.cc
+++ b/gcc/diagnostics/text-sink.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostics/diagram.h"
#include "diagnostics/text-sink.h"
#include "diagnostics/buffering.h"
+#include "diagnostics/dumping.h"
#include "text-art/theme.h"
/* Disable warnings about quoting issues in the pp_xxx calls below
@@ -76,7 +77,7 @@ text_sink_buffer::text_sink_buffer (sink &sink_)
void
text_sink_buffer::dump (FILE *out, int indent) const
{
- fprintf (out, "%*stext_sink_buffer:\n", indent, "");
+ dumping::emit_heading (out, indent, "text_sink_buffer");
m_output_buffer.dump (out, indent + 2);
}
@@ -156,18 +157,19 @@ text_sink::~text_sink ()
}
void
-text_sink::dump (FILE *out, int indent) const
-{
- fprintf (out, "%*stext_sink\n", indent, "");
- fprintf (out, "%*sm_follows_reference_printer: %s\n",
- indent, "",
- m_follows_reference_printer ? "true" : "false");
- sink::dump (out, indent);
- fprintf (out, "%*ssaved_output_buffer:\n", indent + 2, "");
+text_sink::dump (FILE *outfile, int indent) const
+{
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_follows_reference_printer);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_show_nesting);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_show_locations_in_nesting);
+ DIAGNOSTICS_DUMPING_EMIT_FIELD (m_show_nesting_levels);
+
+ sink::dump (outfile, indent);
+ dumping::emit_heading (outfile, indent, "saved_output_buffer");
if (m_saved_output_buffer)
- m_saved_output_buffer->dump (out, indent + 4);
+ m_saved_output_buffer->dump (outfile, indent + 2);
else
- fprintf (out, "%*s(none):\n", indent + 4, "");
+ dumping::emit_none (outfile, indent + 2);
}
void
@@ -612,7 +614,7 @@ text_sink::get_location_text (const expanded_location &s) const
The result is a statically allocated buffer. */
const char *
-maybe_line_and_column (int line, int col)
+text_sink::maybe_line_and_column (int line, int col)
{
static char result[32];
diff --git a/gcc/diagnostics/text-sink.h b/gcc/diagnostics/text-sink.h
index 5c60976..f280e72 100644
--- a/gcc/diagnostics/text-sink.h
+++ b/gcc/diagnostics/text-sink.h
@@ -51,6 +51,12 @@ public:
{}
~text_sink ();
+ text_sink *dyn_cast_text_sink () final override { return this; }
+
+ void dump_kind (FILE *out) const override
+ {
+ fprintf (out, "text_sink");
+ }
void dump (FILE *out, int indent) const override;
std::unique_ptr<per_sink_buffer>
@@ -127,6 +133,8 @@ public:
return m_source_printing;
}
+ static const char *maybe_line_and_column (int line, int col);
+
protected:
void print_any_cwe (const diagnostic_info &diagnostic);
void print_any_rules (const diagnostic_info &diagnostic);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 33ae98c..28466c4 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -322,6 +322,9 @@ Objective-C and Objective-C++ Dialects}.
-fno-diagnostics-show-cwe
-fno-diagnostics-show-rules
-fno-diagnostics-show-highlight-colors
+-fno-diagnostics-show-nesting
+-fno-diagnostics-show-nesting-locations
+-fdiagnostics-show-nesting-levels
-fdiagnostics-minimum-margin-width=@var{width}
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type
@@ -5429,7 +5432,8 @@ options:
-fdiagnostics-urls=never
-fdiagnostics-path-format=separate-events
-fdiagnostics-text-art-charset=none
--fno-diagnostics-show-event-links}
+-fno-diagnostics-show-event-links
+-fno-diagnostics-show-nesting}
In the future, if GCC changes the default appearance of its diagnostics, the
corresponding option to disable the new behavior will be added to this list.
@@ -6051,6 +6055,40 @@ emoji variant of the character).
The default is @samp{emoji}, except when the environment variable @env{LANG}
is set to @samp{C}, in which case the default is @samp{ascii}.
+@opindex fno-diagnostics-show-nesting
+@opindex fdiagnostics-show-nesting
+@item -fno-diagnostics-show-nesting
+Some GCC diagnostics have an internal tree-like structure of nested
+sub-diagnostics, such as for problems when instantiating C++ templates.
+
+By default GCC uses indentation and bullet points in its text output to
+show the nesting structure of these diagnostics, moves location
+information to separate lines to make the structure clearer, and
+eliminates redundant repeated information.
+
+Selecting @option{-fno-diagnostics-show-nesting} suppresses this
+indentation, reformatting, and elision, restoring an older `look'' for the
+diagnostics.
+
+@opindex fno-diagnostics-show-nesting-locations
+@opindex fdiagnostics-show-nesting-locations
+@item -fno-diagnostics-show-nesting-locations
+
+When @option{fdiagnostics-show-nesting} is enabled, file names and
+line- and column- numbers are displayed on separate lines from the
+messages. This location information can be disabled altogether with
+@option{-fno-diagnostics-show-nesting-locations}.
+This option exists for use by GCC developers, for writing DejaGnu test cases.
+
+@opindex fdiagnostics-show-nesting-levels
+@opindex fno-diagnostics-show-nesting-levels
+@item -fdiagnostics-show-nesting-levels
+When @option{fdiagnostics-show-nesting} is enabled, use
+@option{fdiagnostics-show-nesting-levels} to also display numbers
+showing the depth of the nesting.
+This option exists for use by GCC developers for debugging nested
+diagnostics, but may be of use to plugin authors.
+
@opindex fdiagnostics-format
@item -fdiagnostics-format=@var{FORMAT}
Select a different format for printing diagnostics.
@@ -6099,18 +6137,18 @@ Supported keys are:
Override colorization settings from @option{-fdiagnostics-color} for this
text output.
-@item experimental-nesting=@r{[}yes@r{|}no@r{]}
-Enable an experimental mode that emphasizes hierarchical relationships
-within diagnostics messages, displaying location information on separate
-lines.
+@item show-nesting=@r{[}yes@r{|}no@r{]}
+Enable a mode that emphasizes hierarchical relationships
+within diagnostics messages, as per @option{-fdiagnostics-show-nesting}.
+Defaults to @code{yes}.
-@item experimental-nesting-show-locations=@r{[}yes@r{|}no@r{]}
-If @code{experimental-nesting=yes}, then by default locations are
+@item show-nesting-locations=@r{[}yes@r{|}no@r{]}
+If @code{show-nesting=yes}, then by default locations are
shown; set this key to @code{no} to disable printing such locations.
This exists for use by GCC developers, for writing DejaGnu test cases.
-@item experimental-nesting-show-levels=@r{[}yes@r{|}no@r{]}
-This is a debugging option for use with @code{experimental-nesting=yes}.
+@item show-nesting-levels=@r{[}yes@r{|}no@r{]}
+This is a debugging option for use with @code{show-nesting=yes}.
Set this key to @code{yes} to print explicit nesting levels in the output.
This exists for use by GCC developers.
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index 03fca97..dbe3ad0 100644
--- a/gcc/lto-wrapper.cc
+++ b/gcc/lto-wrapper.cc
@@ -320,6 +320,9 @@ merge_and_complain (vec<cl_decoded_option> &decoded_options,
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
+ case OPT_fdiagnostics_show_nesting:
+ case OPT_fdiagnostics_show_nesting_locations:
+ case OPT_fdiagnostics_show_nesting_levels:
case OPT_fshow_column:
case OPT_fcommon:
case OPT_fgnu_tm:
@@ -739,6 +742,9 @@ append_compiler_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
+ case OPT_fdiagnostics_show_nesting:
+ case OPT_fdiagnostics_show_nesting_locations:
+ case OPT_fdiagnostics_show_nesting_levels:
case OPT_fshow_column:
case OPT_fPIC:
case OPT_fpic:
@@ -801,6 +807,9 @@ append_diag_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
+ case OPT_fdiagnostics_show_nesting:
+ case OPT_fdiagnostics_show_nesting_locations:
+ case OPT_fdiagnostics_show_nesting_levels:
case OPT_fshow_column:
break;
default:
diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
index e6d7f4d..379402e 100644
--- a/gcc/opts-common.cc
+++ b/gcc/opts-common.cc
@@ -1096,7 +1096,8 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv,
"-fdiagnostics-urls=never",
"-fdiagnostics-path-format=separate-events",
"-fdiagnostics-text-art-charset=none",
- "-fno-diagnostics-show-event-links"
+ "-fno-diagnostics-show-event-links",
+ "-fno-diagnostics-show-nesting"
/* We don't put "-fno-diagnostics-show-highlight-colors" here
as -fdiagnostics-color=never makes it redundant. */
};
diff --git a/gcc/opts.cc b/gcc/opts.cc
index b6d25bf..a02d017 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3016,11 +3016,12 @@ common_handle_option (struct gcc_options *opts,
break;
case OPT_fdiagnostics_column_unit_:
- dc->m_column_unit = (enum diagnostics_column_unit)value;
+ dc->get_column_options ().m_column_unit
+ = (enum diagnostics_column_unit)value;
break;
case OPT_fdiagnostics_column_origin_:
- dc->m_column_origin = value;
+ dc->get_column_options ().m_column_origin = value;
break;
case OPT_fdiagnostics_escape_format_:
@@ -3051,6 +3052,18 @@ common_handle_option (struct gcc_options *opts,
dc->set_show_option_requested (value);
break;
+ case OPT_fdiagnostics_show_nesting:
+ dc->set_show_nesting (value);
+ break;
+
+ case OPT_fdiagnostics_show_nesting_locations:
+ dc->set_show_nesting_locations (value);
+ break;
+
+ case OPT_fdiagnostics_show_nesting_levels:
+ dc->set_show_nesting_levels (value);
+ break;
+
case OPT_fdiagnostics_minimum_margin_width_:
dc->get_source_printing_options ().min_margin_width = value;
break;
@@ -3408,7 +3421,7 @@ common_handle_option (struct gcc_options *opts,
case OPT_ftabstop_:
/* It is documented that we silently ignore silly values. */
if (value >= 1 && value <= 100)
- dc->m_tabstop = value;
+ dc->get_column_options ().m_tabstop = value;
break;
case OPT_freport_bug:
@@ -3879,6 +3892,9 @@ gen_command_line_string (cl_decoded_option *options,
case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_color_:
case OPT_fdiagnostics_format_:
+ case OPT_fdiagnostics_show_nesting:
+ case OPT_fdiagnostics_show_nesting_locations:
+ case OPT_fdiagnostics_show_nesting_levels:
case OPT_fverbose_asm:
case OPT____:
case OPT__sysroot_:
diff --git a/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1-truncated.C b/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1-truncated.C
index 0cb1610..5b5e3fe 100644
--- a/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1-truncated.C
+++ b/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1-truncated.C
@@ -1,6 +1,6 @@
// { dg-do compile { target c++17 } }
// { dg-options "-fconcepts" }
-// { dg-additional-options "-fdiagnostics-set-output=text:experimental-nesting=yes,experimental-nesting-show-locations=no" }
+// { dg-additional-options "-fdiagnostics-set-output=text:show-nesting=yes,show-nesting-locations=no" }
struct dog {};
struct cat {};
diff --git a/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1.C b/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1.C
index e642676..a071b55 100644
--- a/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1.C
+++ b/gcc/testsuite/g++.dg/concepts/nested-diagnostics-1.C
@@ -1,6 +1,6 @@
// { dg-do compile { target c++17 } }
// { dg-options "-fconcepts" }
-// { dg-additional-options "-fdiagnostics-set-output=text:experimental-nesting=yes,experimental-nesting-show-locations=no" }
+// { dg-additional-options "-fdiagnostics-set-output=text:show-nesting=yes,show-nesting-locations=no" }
// { dg-additional-options "-fconcepts-diagnostics-depth=3" }
struct dog {};
diff --git a/gcc/testsuite/g++.dg/concepts/nested-diagnostics-2.C b/gcc/testsuite/g++.dg/concepts/nested-diagnostics-2.C
index cc15f11..9530bc1 100644
--- a/gcc/testsuite/g++.dg/concepts/nested-diagnostics-2.C
+++ b/gcc/testsuite/g++.dg/concepts/nested-diagnostics-2.C
@@ -1,6 +1,6 @@
// { dg-do compile { target c++17 } }
// { dg-options "-fconcepts" }
-// { dg-additional-options "-fdiagnostics-set-output=text:experimental-nesting=yes,experimental-nesting-show-locations=no" }
+// { dg-additional-options "-fdiagnostics-set-output=text:show-nesting=yes,show-nesting-locations=no" }
struct dog{};
struct cat{};
diff --git a/gcc/testsuite/g++.dg/torture/noncall-eh-1.C b/gcc/testsuite/g++.dg/torture/noncall-eh-1.C
new file mode 100644
index 0000000..ea8fd79
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/noncall-eh-1.C
@@ -0,0 +1,26 @@
+// { dg-do compile }
+// For slim LTO there's no optimized dump
+// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
+// { dg-additional-options "-fnon-call-exceptions -fexceptions -fdump-tree-optimized-eh" }
+
+// PR tree-optimization/120599
+// Copying prop for aggregates should not touch `a = *__val` since that statement
+// can throw (internally) so we need to be able to keep the landing pad.
+
+struct RefitOption {
+ char subtype;
+ int string;
+} n;
+void h(RefitOption) __attribute__((nothrow));
+void k(RefitOption *__val, RefitOption a)
+{
+ try {
+ a = *__val;
+ RefitOption __trans_tmp_2 = a;
+ h(__trans_tmp_2);
+ }
+ catch(...){}
+}
+
+// Make sure There is a landing pad for the non-call exception from the aggregate load.
+// { dg-final { scan-tree-dump "LP " "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-no-show-nesting.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-no-show-nesting.c
new file mode 100644
index 0000000..3492899
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-no-show-nesting.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-diagnostics-show-nesting" } */
+
+extern void foo (void);
+
+void test_nesting (void)
+{
+ foo (); /* { dg-error "top-level error" } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-show-nesting.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-show-nesting.c
new file mode 100644
index 0000000..8fc2edb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-show-nesting.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-show-nesting" } */
+
+extern void foo (void);
+
+void test_nesting (void)
+{
+ foo (); /* { dg-error "top-level error" } */
+}
+
+/* { dg-begin-multiline-output "" }
+ * child 0
+ * grandchild 0 0
+ * grandchild 0 1
+ * grandchild 0 2
+ * child 1
+ * grandchild 1 0
+ * grandchild 1 1
+ * grandchild 1 2
+ * child 2
+ * grandchild 2 0
+ * grandchild 2 1
+ * grandchild 2 2
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-show-levels.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-show-levels.c
index f44c8eb..4be52fe 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-show-levels.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-show-levels.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fdiagnostics-set-output=text:experimental-nesting=yes,experimental-nesting-show-levels=yes" } */
+/* { dg-options "-fdiagnostics-set-output=text:show-nesting=yes,show-nesting-levels=yes" } */
extern void foo (void);
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-unicode.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-unicode.c
index 39e29f7..c069c3f 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-unicode.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented-unicode.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fdiagnostics-set-output=text:experimental-nesting=yes -fdiagnostics-text-art-charset=unicode" } */
+/* { dg-options "-fdiagnostics-set-output=text:show-nesting=yes -fdiagnostics-text-art-charset=unicode" } */
extern void foo (void);
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented.c
index e103429..a35254d 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-text-indented.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fdiagnostics-set-output=text:experimental-nesting=yes" } */
+/* { dg-options "-fdiagnostics-set-output=text:show-nesting=yes" } */
extern void foo (void);
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 3bb6063..c7cc36c 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -112,6 +112,8 @@ set plugin_test_list [list \
diagnostic-test-graphs-html.c \
diagnostic-test-graphs-sarif.c } \
{ diagnostic_plugin_test_nesting.cc \
+ diagnostic-test-nesting-show-nesting.c \
+ diagnostic-test-nesting-no-show-nesting.c \
diagnostic-test-nesting-text-plain.c \
diagnostic-test-nesting-text-indented.c \
diagnostic-test-nesting-text-indented-show-levels.c \
diff --git a/gcc/testsuite/gcc.dg/pr118946-1.c b/gcc/testsuite/gcc.dg/pr118946-1.c
new file mode 100644
index 0000000..6cf2661
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr118946-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-forwprop1-details" } */
+
+/* PR tree-optimization/118946 */
+
+void f(char *a)
+{
+ char t[1024] = {};
+ __builtin_memcpy(a, t, 10);
+}
+
+/* We should be able to optimize the memcpy into a memset here. */
+/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "memset " 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "memcpy " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr121422-1.c b/gcc/testsuite/gcc.dg/torture/pr121422-1.c
new file mode 100644
index 0000000..136f80d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121422-1.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* PR tree-optimization/121422 */
+
+struct s1
+{
+ char a[4];
+};
+struct s1 b;
+char t[4];
+
+/* if both t and b startout zero initialized before this function,
+ t should end up being:
+ {0, 0, 1, 0}
+ while b.a should end up being:
+ {0, 0, 0, 1}
+*/
+__attribute__((noipa,noinline))
+void f(void)
+{
+ b = (struct s1){};
+ b.a[3] = 1;
+ /* This memcpy should stay a memcpy and not become memset. */
+ __builtin_memcpy(&t[0], &b.a[1], 3*sizeof(t[0]));
+}
+
+
+int main()
+{
+ f();
+ for(int i = 0; i < 4; i++)
+ {
+ if (t[i] != (i == 2 ? 1 : 0))
+ __builtin_abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr121422-2.c b/gcc/testsuite/gcc.dg/torture/pr121422-2.c
new file mode 100644
index 0000000..570559c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121422-2.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* PR tree-optimization/121422 */
+
+struct s1
+{
+ char a[4];
+};
+struct s1 b;
+char t[4];
+
+/* if both t and b startout zero initialized before this function,
+ t should end up being:
+ {0, 0, 1, 0}
+ while b.a should end up being:
+ {0, 0, 0, 1}
+*/
+__attribute__((noipa,noinline))
+void f(void)
+{
+ __builtin_memset(&b.a[1], 0, 2);
+ b.a[3] = 1;
+ /* This memcpy should stay a memcpy and not become memset. */
+ __builtin_memcpy(&t[0], &b.a[1], 3);
+}
+
+
+int main()
+{
+ f();
+ for(int i = 0; i < 4; i++)
+ {
+ if (t[i] != (i == 2 ? 1 : 0))
+ __builtin_abort();
+ }
+}
+
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index d349d83..d264674 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -1094,6 +1094,12 @@ general_init (const char *argv0, bool init_signals, unique_argv original_argv)
= global_options_init.x_flag_show_column;
global_dc->set_show_highlight_colors
(global_options_init.x_flag_diagnostics_show_highlight_colors);
+ global_dc->set_show_nesting
+ (global_options_init.x_flag_diagnostics_show_nesting);
+ global_dc->set_show_nesting_locations
+ (global_options_init.x_flag_diagnostics_show_nesting_locations);
+ global_dc->set_show_nesting_levels
+ (global_options_init.x_flag_diagnostics_show_nesting_levels);
global_dc->set_internal_error_callback (internal_error_function);
const unsigned lang_mask = lang_hooks.option_lang_mask ();
global_dc->set_option_id_manager
diff --git a/gcc/tree-diagnostic.cc b/gcc/tree-diagnostic.cc
index 3761fc0..20183c8 100644
--- a/gcc/tree-diagnostic.cc
+++ b/gcc/tree-diagnostic.cc
@@ -110,7 +110,7 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
to the DIAGNOSTIC location. */
static void
-set_inlining_locations (diagnostics::context *,
+set_inlining_locations (const diagnostics::context &,
diagnostics::diagnostic_info *diagnostic)
{
location_t loc = diagnostic_location (diagnostic);
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 43b1c9d..3d38d88 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -1190,117 +1190,55 @@ constant_pointer_difference (tree p1, tree p2)
return NULL_TREE;
}
-
-/* Optimize
- a = {};
- b = a;
- into
- a = {};
- b = {};
- Similarly for memset (&a, ..., sizeof (a)); instead of a = {};
- and/or memcpy (&b, &a, sizeof (a)); instead of b = a; */
-
+/* Helper function for optimize_aggr_zeroprop.
+ Props the zeroing (memset, VAL) that was done in DEST+OFFSET:LEN
+ (DEFSTMT) into the STMT. Returns true if the STMT was updated. */
static bool
-optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree len)
+optimize_aggr_zeroprop_1 (gimple *defstmt, gimple *stmt,
+ tree dest, poly_int64 offset, tree val,
+ poly_offset_int len)
{
- ao_ref read;
- gimple *stmt = gsi_stmt (*gsip);
- if (gimple_has_volatile_ops (stmt))
- return false;
-
- tree src2 = NULL_TREE, len2 = NULL_TREE;
- poly_int64 offset, offset2;
- tree val = integer_zero_node;
- bool len_was_null = len == NULL_TREE;
- if (len == NULL_TREE)
- len = (TREE_CODE (src) == COMPONENT_REF
- ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1))
- : TYPE_SIZE_UNIT (TREE_TYPE (src)));
- if (len == NULL_TREE
- || !poly_int_tree_p (len))
- return false;
+ tree src2;
+ tree len2 = NULL_TREE;
+ poly_int64 offset2;
- ao_ref_init (&read, src);
- tree vuse = gimple_vuse (stmt);
- gimple *defstmt;
- unsigned limit = param_sccvn_max_alias_queries_per_access;
- do {
- /* If the vuse is the default definition, then there is no stores beforhand. */
- if (SSA_NAME_IS_DEFAULT_DEF (vuse))
- return false;
- defstmt = SSA_NAME_DEF_STMT (vuse);
- if (is_a <gphi*>(defstmt))
- return false;
- if (limit-- == 0)
- return false;
- /* If the len was null, then we can use TBBA. */
- if (stmt_may_clobber_ref_p_1 (defstmt, &read,
- /* tbaa_p = */ len_was_null))
- break;
- vuse = gimple_vuse (defstmt);
- } while (true);
-
- if (gimple_store_p (defstmt)
- && gimple_assign_single_p (defstmt)
- && TREE_CODE (gimple_assign_rhs1 (defstmt)) == STRING_CST
- && !gimple_clobber_p (defstmt))
+ if (gimple_call_builtin_p (stmt, BUILT_IN_MEMCPY)
+ && TREE_CODE (gimple_call_arg (stmt, 1)) == ADDR_EXPR
+ && poly_int_tree_p (gimple_call_arg (stmt, 2)))
{
- tree str = gimple_assign_rhs1 (defstmt);
- src2 = gimple_assign_lhs (defstmt);
- /* The string must contain all null char's for now. */
- for (int i = 0; i < TREE_STRING_LENGTH (str); i++)
- {
- if (TREE_STRING_POINTER (str)[i] != 0)
- {
- src2 = NULL_TREE;
- break;
- }
- }
- }
- else if (gimple_store_p (defstmt)
- && gimple_assign_single_p (defstmt)
- && TREE_CODE (gimple_assign_rhs1 (defstmt)) == CONSTRUCTOR
- && !gimple_clobber_p (defstmt))
- src2 = gimple_assign_lhs (defstmt);
- else if (gimple_call_builtin_p (defstmt, BUILT_IN_MEMSET)
- && TREE_CODE (gimple_call_arg (defstmt, 0)) == ADDR_EXPR
- && TREE_CODE (gimple_call_arg (defstmt, 1)) == INTEGER_CST)
- {
- src2 = TREE_OPERAND (gimple_call_arg (defstmt, 0), 0);
- len2 = gimple_call_arg (defstmt, 2);
- val = gimple_call_arg (defstmt, 1);
- /* For non-0 val, we'd have to transform stmt from assignment
- into memset (only if dest is addressable). */
- if (!integer_zerop (val) && is_gimple_assign (stmt))
- src2 = NULL_TREE;
+ src2 = TREE_OPERAND (gimple_call_arg (stmt, 1), 0);
+ len2 = gimple_call_arg (stmt, 2);
}
+ else if (gimple_assign_load_p (stmt) && gimple_store_p (stmt))
+ {
+ src2 = gimple_assign_rhs1 (stmt);
+ len2 = (TREE_CODE (src2) == COMPONENT_REF
+ ? DECL_SIZE_UNIT (TREE_OPERAND (src2, 1))
+ : TYPE_SIZE_UNIT (TREE_TYPE (src2)));
+ /* Can only handle zero memsets. */
+ if (!integer_zerop (val))
+ return false;
+ }
+ else
+ return false;
- if (src2 == NULL_TREE)
- return false;
-
- if (len2 == NULL_TREE)
- len2 = (TREE_CODE (src2) == COMPONENT_REF
- ? DECL_SIZE_UNIT (TREE_OPERAND (src2, 1))
- : TYPE_SIZE_UNIT (TREE_TYPE (src2)));
if (len2 == NULL_TREE
|| !poly_int_tree_p (len2))
return false;
- src = get_addr_base_and_unit_offset (src, &offset);
src2 = get_addr_base_and_unit_offset (src2, &offset2);
- if (src == NULL_TREE
- || src2 == NULL_TREE
- || maybe_lt (offset, offset2))
+ if (src2 == NULL_TREE
+ || maybe_lt (offset2, offset))
return false;
- if (!operand_equal_p (src, src2, 0))
+ if (!operand_equal_p (dest, src2, 0))
return false;
- /* [ src + offset2, src + offset2 + len2 - 1 ] is set to val.
+ /* [ dest + offset, dest + offset + len - 1 ] is set to val.
Make sure that
- [ src + offset, src + offset + len - 1 ] is a subset of that. */
- if (maybe_gt (wi::to_poly_offset (len) + (offset - offset2),
- wi::to_poly_offset (len2)))
+ [ dest + offset2, dest + offset2 + len2 - 1 ] is a subset of that. */
+ if (maybe_gt (wi::to_poly_offset (len2) + (offset2 - offset),
+ len))
return false;
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1310,7 +1248,7 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
fprintf (dump_file, "after previous\n ");
print_gimple_stmt (dump_file, defstmt, 0, dump_flags);
}
-
+ gimple *orig_stmt = stmt;
/* For simplicity, don't change the kind of the stmt,
turn dest = src; into dest = {}; and memcpy (&dest, &src, len);
into memset (&dest, val, len);
@@ -1320,8 +1258,10 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
of dest, dest isn't volatile. */
if (is_gimple_assign (stmt))
{
- tree ctor = build_constructor (TREE_TYPE (dest), NULL);
- gimple_assign_set_rhs_from_tree (gsip, ctor);
+ tree ctor_type = TREE_TYPE (gimple_assign_lhs (stmt));
+ tree ctor = build_constructor (ctor_type, NULL);
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, ctor);
update_stmt (stmt);
statistics_counter_event (cfun, "copy zeroing propagation of aggregate", 1);
}
@@ -1341,89 +1281,210 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
fprintf (dump_file, "into\n ");
print_gimple_stmt (dump_file, stmt, 0, dump_flags);
}
+
+ /* Mark the bb for eh cleanup if needed. */
+ if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
+ bitmap_set_bit (to_purge, gimple_bb (stmt)->index);
+
return true;
}
-/* Optimizes
- a = c;
+
+/* Optimize
+ a = {}; // DEST = value ;; LEN(nullptr)
b = a;
into
- a = c;
- b = c;
- GSIP is the second statement and SRC is the common
- between the statements.
-*/
+ a = {};
+ b = {};
+ Similarly for memset (&a, ..., sizeof (a)); instead of a = {};
+ and/or memcpy (&b, &a, sizeof (a)); instead of b = a; */
+
static bool
-optimize_agr_copyprop (gimple_stmt_iterator *gsip)
+optimize_aggr_zeroprop (gimple_stmt_iterator *gsip)
{
+ ao_ref read;
gimple *stmt = gsi_stmt (*gsip);
if (gimple_has_volatile_ops (stmt))
return false;
- tree dest = gimple_assign_lhs (stmt);
- tree src = gimple_assign_rhs1 (stmt);
- /* If the statement is `src = src;` then ignore it. */
- if (operand_equal_p (dest, src, 0))
- return false;
+ tree dest = NULL_TREE;
+ tree val = integer_zero_node;
+ tree len = NULL_TREE;
+ bool can_use_tbba = true;
+ bool changed = false;
+
+ if (gimple_call_builtin_p (stmt, BUILT_IN_MEMSET)
+ && TREE_CODE (gimple_call_arg (stmt, 0)) == ADDR_EXPR
+ && TREE_CODE (gimple_call_arg (stmt, 1)) == INTEGER_CST
+ && poly_int_tree_p (gimple_call_arg (stmt, 2)))
+ {
+ dest = TREE_OPERAND (gimple_call_arg (stmt, 0), 0);
+ len = gimple_call_arg (stmt, 2);
+ val = gimple_call_arg (stmt, 1);
+ ao_ref_init_from_ptr_and_size (&read, gimple_call_arg (stmt, 0), len);
+ can_use_tbba = false;
+ }
+ else if (gimple_store_p (stmt)
+ && gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == STRING_CST)
+ {
+ tree str = gimple_assign_rhs1 (stmt);
+ dest = gimple_assign_lhs (stmt);
+ ao_ref_init (&read, dest);
+ /* The string must contain all null char's for now. */
+ for (int i = 0; i < TREE_STRING_LENGTH (str); i++)
+ {
+ if (TREE_STRING_POINTER (str)[i] != 0)
+ {
+ dest = NULL_TREE;
+ break;
+ }
+ }
+ }
+ else if (gimple_store_p (stmt)
+ && gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == CONSTRUCTOR
+ && !gimple_clobber_p (stmt))
+ {
+ dest = gimple_assign_lhs (stmt);
+ ao_ref_init (&read, dest);
+ }
- tree vuse = gimple_vuse (stmt);
- /* If the vuse is the default definition, then there is no store beforehand. */
- if (SSA_NAME_IS_DEFAULT_DEF (vuse))
+ if (dest == NULL_TREE)
return false;
- gimple *defstmt = SSA_NAME_DEF_STMT (vuse);
- if (!gimple_assign_load_p (defstmt)
- || !gimple_store_p (defstmt))
+
+ if (len == NULL_TREE)
+ len = (TREE_CODE (dest) == COMPONENT_REF
+ ? DECL_SIZE_UNIT (TREE_OPERAND (dest, 1))
+ : TYPE_SIZE_UNIT (TREE_TYPE (dest)));
+ if (len == NULL_TREE
+ || !poly_int_tree_p (len))
return false;
- if (gimple_has_volatile_ops (defstmt))
+
+ /* This store needs to be on the byte boundary and pointing to an object. */
+ poly_int64 offset;
+ tree dest_base = get_addr_base_and_unit_offset (dest, &offset);
+ if (dest_base == NULL_TREE)
return false;
- tree dest2 = gimple_assign_lhs (defstmt);
- tree src2 = gimple_assign_rhs1 (defstmt);
+ /* Setup the worklist. */
+ auto_vec<std::pair<tree, unsigned>> worklist;
+ unsigned limit = param_sccvn_max_alias_queries_per_access;
+ worklist.safe_push (std::make_pair (gimple_vdef (stmt), limit));
- /* If the original store is `src2 = src2;` skip over it. */
- if (operand_equal_p (src2, dest2, 0))
- return false;
- if (!operand_equal_p (src, dest2, 0))
+ while (!worklist.is_empty ())
+ {
+ std::pair<tree, unsigned> top = worklist.pop ();
+ tree vdef = top.first;
+ limit = top.second;
+ gimple *use_stmt;
+ imm_use_iterator iter;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
+ {
+ /* Handling PHI nodes might not be worth it so don't. */
+ if (is_a <gphi*> (use_stmt))
+ continue;
+
+ /* If this statement does not clobber add the vdef stmt to the
+ worklist. */
+ if (gimple_vdef (use_stmt)
+ && !stmt_may_clobber_ref_p_1 (use_stmt, &read,
+ /* tbaa_p = */ can_use_tbba)
+ && limit != 0)
+ worklist.safe_push (std::make_pair (gimple_vdef (use_stmt),
+ limit - 1));
+
+ if (optimize_aggr_zeroprop_1 (stmt, use_stmt, dest_base, offset,
+ val, wi::to_poly_offset (len)))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+/* Optimizes
+ DEST = SRC;
+ DEST2 = DEST; # DEST2 = SRC2;
+ into
+ DEST = SRC;
+ DEST2 = SRC;
+ GSIP is the first statement and SRC is the common
+ between the statements.
+*/
+static bool
+optimize_agr_copyprop (gimple_stmt_iterator *gsip)
+{
+ gimple *stmt = gsi_stmt (*gsip);
+ if (gimple_has_volatile_ops (stmt))
return false;
+ /* Can't prop if the statement could throw. */
+ if (stmt_could_throw_p (cfun, stmt))
+ return false;
- /* For 2 memory refences and using a temporary to do the copy,
- don't remove the temporary as the 2 memory references might overlap.
- Note t does not need to be decl as it could be field.
- See PR 22237 for full details.
- E.g.
- t = *a;
- *b = t;
- Cannot be convert into
- t = *a;
- *b = *a;
- Though the following is allowed to be done:
- t = *a;
- *a = t;
- And convert it into:
- t = *a;
- *a = *a;
- */
- if (!operand_equal_p (src2, dest, 0)
- && !DECL_P (dest) && !DECL_P (src2))
+ tree dest = gimple_assign_lhs (stmt);
+ tree src = gimple_assign_rhs1 (stmt);
+ /* If the statement is `src = src;` then ignore it. */
+ if (operand_equal_p (dest, src, 0))
return false;
- if (dump_file && (dump_flags & TDF_DETAILS))
+ tree vdef = gimple_vdef (stmt);
+ imm_use_iterator iter;
+ gimple *use_stmt;
+ bool changed = false;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
{
- fprintf (dump_file, "Simplified\n ");
- print_gimple_stmt (dump_file, stmt, 0, dump_flags);
- fprintf (dump_file, "after previous\n ");
- print_gimple_stmt (dump_file, defstmt, 0, dump_flags);
- }
- gimple_assign_set_rhs_from_tree (gsip, unshare_expr (src2));
- update_stmt (stmt);
+ if (!gimple_assign_load_p (use_stmt)
+ || !gimple_store_p (use_stmt))
+ continue;
+ if (gimple_has_volatile_ops (use_stmt))
+ continue;
+ tree dest2 = gimple_assign_lhs (use_stmt);
+ tree src2 = gimple_assign_rhs1 (use_stmt);
+ /* If the new store is `src2 = src2;` skip over it. */
+ if (operand_equal_p (src2, dest2, 0))
+ continue;
+ if (!operand_equal_p (dest, src2, 0))
+ continue;
+ /* For 2 memory refences and using a temporary to do the copy,
+ don't remove the temporary as the 2 memory references might overlap.
+ Note t does not need to be decl as it could be field.
+ See PR 22237 for full details.
+ E.g.
+ t = *a; #DEST = SRC;
+ *b = t; #DEST2 = SRC2;
+ Cannot be convert into
+ t = *a;
+ *b = *a;
+ Though the following is allowed to be done:
+ t = *a;
+ *a = t;
+ And convert it into:
+ t = *a;
+ *a = *a;
+ */
+ if (!operand_equal_p (dest2, src, 0)
+ && !DECL_P (dest2) && !DECL_P (src))
+ continue;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Simplified\n ");
+ print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
+ fprintf (dump_file, "after previous\n ");
+ print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+ }
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (src));
+ update_stmt (use_stmt);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "into\n ");
- print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "into\n ");
+ print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
+ }
+ statistics_counter_event (cfun, "copy prop for aggregate", 1);
+ changed = true;
}
- statistics_counter_event (cfun, "copy prop for aggregate", 1);
- return true;
+ return changed;
}
/* *GSI_P is a GIMPLE_CALL to a builtin function.
@@ -1463,22 +1524,6 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
switch (DECL_FUNCTION_CODE (callee2))
{
- case BUILT_IN_MEMCPY:
- if (gimple_call_num_args (stmt2) == 3)
- {
- tree dest = gimple_call_arg (stmt2, 0);
- tree src = gimple_call_arg (stmt2, 1);
- tree len = gimple_call_arg (stmt2, 2);
- /* Try to optimize the memcpy to memset if src
- and dest are addresses. */
- if (TREE_CODE (dest) == ADDR_EXPR
- && TREE_CODE (src) == ADDR_EXPR
- && TREE_CODE (len) == INTEGER_CST
- && optimize_memcpy_to_memset (gsi_p, TREE_OPERAND (dest, 0),
- TREE_OPERAND (src, 0), len))
- return true;
- }
- break;
case BUILT_IN_MEMCHR:
if (gimple_call_num_args (stmt2) == 3
&& (res = gimple_call_lhs (stmt2)) != nullptr
@@ -1540,6 +1585,13 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
break;
case BUILT_IN_MEMSET:
+ if (gimple_call_num_args (stmt2) == 3)
+ {
+ /* Try to prop the zeroing/value of the memset to memcpy
+ if the dest is an address and the value is a constant. */
+ if (optimize_aggr_zeroprop (gsi_p))
+ return true;
+ }
if (gimple_call_num_args (stmt2) != 3
|| gimple_call_lhs (stmt2)
|| CHAR_BIT != 8
@@ -4858,21 +4910,16 @@ pass_forwprop::execute (function *fun)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt);
- if (gimple_assign_load_p (stmt) && gimple_store_p (stmt))
+ if (gimple_store_p (stmt) && optimize_aggr_zeroprop (&gsi))
{
- if (optimize_memcpy_to_memset (&gsi,
- gimple_assign_lhs (stmt),
- gimple_assign_rhs1 (stmt),
- /* len = */NULL_TREE))
- {
- changed = true;
- break;
- }
- if (optimize_agr_copyprop (&gsi))
- {
- changed = true;
- break;
- }
+ changed = true;
+ break;
+ }
+ if (gimple_assign_load_p (stmt) && gimple_store_p (stmt)
+ && optimize_agr_copyprop (&gsi))
+ {
+ changed = true;
+ break;
}
if (TREE_CODE_CLASS (code) == tcc_comparison)
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index f7b48dc..e258f94 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -87,6 +87,7 @@ CC = @CC@
CFLAGS = @CFLAGS@
RANLIB = @RANLIB@
LN_S = @LN_S@
+WERROR = @WERROR@
PWD_COMMAND = $${PWDCMD-pwd}
diff --git a/libgcc/config/aarch64/t-aarch64 b/libgcc/config/aarch64/t-aarch64
index d4c5922..c7d83c7 100644
--- a/libgcc/config/aarch64/t-aarch64
+++ b/libgcc/config/aarch64/t-aarch64
@@ -30,4 +30,4 @@ LIB2ADDEH += \
$(srcdir)/config/aarch64/__arm_za_disable.S
SHLIB_MAPFILES += $(srcdir)/config/aarch64/libgcc-sme.ver
-LIBGCC2_CFLAGS += -Werror -Wno-prio-ctor-dtor
+LIBGCC2_CFLAGS += $(WERROR) -Wno-prio-ctor-dtor
diff --git a/libgcc/configure b/libgcc/configure
index 1841833..d5e80d2 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -586,6 +586,7 @@ ac_unique_file="static-object.mk"
ac_includes_default='/* none */'
ac_subst_vars='LTLIBOBJS
LIBOBJS
+WERROR
md_unwind_header
md_unwind_def_header
unwind_header
@@ -720,6 +721,7 @@ enable_tm_clone_registry
with_glibc_version
enable_tls
with_gcc_major_version_only
+enable_werror
'
ac_precious_vars='build_alias
host_alias
@@ -1362,6 +1364,7 @@ Optional Features:
installations without PT_GNU_EH_FRAME support
--disable-tm-clone-registry disable TM clone registry
--enable-tls Use thread-local storage [default=yes]
+ --enable-werror build with -Werror for selected targets
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -5789,6 +5792,22 @@ fi
+# Check whether --enable-werror was given.
+if test "${enable_werror+set}" = set; then :
+ enableval=$enable_werror;
+case ${enable_werror} in
+ no) WERROR="" ;;
+ *) WERROR="-Werror" ;;
+esac
+
+else
+
+WERROR="-Werror"
+
+fi
+
+
+
# We need multilib support.
ac_config_files="$ac_config_files Makefile"
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 85e4f1b..65cd3c6 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -733,6 +733,20 @@ AC_SUBST(md_unwind_header)
AC_SUBST(sfp_machine_header)
AC_SUBST(thread_header)
+AC_ARG_ENABLE(werror,
+[AS_HELP_STRING([--enable-werror],
+ [build with -Werror for selected targets])],
+[
+case ${enable_werror} in
+ no) WERROR="" ;;
+ *) WERROR="-Werror" ;;
+esac
+],
+[
+WERROR="-Werror"
+])
+AC_SUBST(WERROR)
+
# We need multilib support.
AC_CONFIG_FILES([Makefile])
AC_CONFIG_COMMANDS([default],
diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc
index a7b4b55..eac6e31 100644
--- a/libgcobol/libgcobol.cc
+++ b/libgcobol/libgcobol.cc
@@ -1719,34 +1719,27 @@ int128_to_field(cblc_field_t *var,
case FldPacked:
{
- static const unsigned char bin2pd[100] =
- {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
- } ;
-
// Convert the binary value to packed decimal.
+ int digits = var->digits;
- // Set the destination bytes to zero
- memset(location, 0, length);
+ // Assume for the moment that the res
unsigned char sign_nybble = 0;
- if( !(var->attr & packed_no_sign_e) )
+ if( var->attr & packed_no_sign_e )
+ {
+ // This is COMP-6 packed decimal, with no sign nybble
+ sign_nybble = 0;
+ }
+ else
{
// This is COMP-3 packed decimal, so we need to make room to the
// right of the final decimal digit for the sign nybble:
value *= 10;
+ digits += 1;
// Figure out what the sign nybble is going to be, and make the
// the value positive:
if(var->attr & signable_e)
{
+ // It is signable, so 0xD for negative, and 0xC for positive
if(value < 0)
{
sign_nybble = 0x0D;
@@ -1759,6 +1752,7 @@ int128_to_field(cblc_field_t *var,
}
else
{
+ // The value is not signable, so the sign nybble is 0xF
sign_nybble = 0x0F;
if(value < 0)
{
@@ -1766,43 +1760,25 @@ int128_to_field(cblc_field_t *var,
}
}
}
- // ploc points to the current rightmost byte of the location:
- unsigned char *ploc = location + length -1 ;
- // Build the target from right to left, so that the result is
- // big-endian:
- while( value && ploc >= location )
- {
- *ploc-- = bin2pd[value%100];
- value /= 100;
- }
+ /* We need to check if the value is too big, in case our caller
+ wants to check for the error condition. In any event, we need
+ to make sure the value actually fits, because otherwise the
+ result might have a bad high-place digit for a value with an
+ odd number of places. */
+ __int128 mask = __gg__power_of_ten(digits);
+ size_error = !!(value / mask);
+ value %= mask;
+
+ // We are now set up to do the conversion:
+ __gg__binary_to_packed(location, digits, value);
+
// We can put the sign nybble into place at this point. Note that
// for COMP-6 numbers the sign_nybble value is zero, so the next
// operation is harmless.
location[length -1] |= sign_nybble;
- // If we still have value left, we have a size error
- if( value )
- {
- size_error = true;
- }
- else
- {
- if( ( sign_nybble && !(var->digits&1) )
- || ( !sign_nybble && (var->digits&1) ) )
- {
- // This is either
- // comp-3 with an even number of digits, or
- // comp-6 with an odd number of digits.
- // Either way, the first byte of the target has to have a high
- // nybble of zero. If it's non-zero, then we have a size error:
- if( location[0] & 0xF0 )
- {
- size_error = true;
- }
- }
- }
// And we're done.
break;
}
diff --git a/libgcobol/stringbin.cc b/libgcobol/stringbin.cc
index d35ea82..2cc229e 100644
--- a/libgcobol/stringbin.cc
+++ b/libgcobol/stringbin.cc
@@ -328,3 +328,150 @@ __gg__binary_to_string_internal(char *result, int digits, __int128 value)
return retval;
}
+
+static
+void
+packed_from_combined(COMBINED &combined)
+ {
+ /* The combined.value must be positive at this point.
+
+ The combined.run value has to be the number of places needed to hold
+ combined.value. The proper calculation is (digits+1)/2.
+
+ For a signable value, the caller had to multiple the original value by
+ ten to create room on the right for the sign nybble. */
+
+ static const unsigned char bin2pd[100] =
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ } ;
+
+ COMBINED left;
+ COMBINED right;
+
+ switch(combined.run)
+ {
+ case 1:
+ // We know that val8 has two digits.
+ combined_string[combined.start] = bin2pd[combined.val8];
+ break;
+
+ case 2:
+ // We know that val16 has four digits.
+ combined_string[combined.start ] = bin2pd[combined.val16/100];
+ combined_string[combined.start+1] = bin2pd[combined.val16%100];
+ break;
+
+ case 3:
+ case 4:
+ // We know that val32 can hold up to eight digits. Break it in half.
+ left.start = combined.start;
+ left.run = combined.run - 2;
+ left.val16 = combined.val32 / 10000;
+
+ right.start = combined.start+left.run;
+ right.run = 2;
+ right.val16 = combined.val32 % 10000;
+
+ packed_from_combined(left);
+ packed_from_combined(right);
+ break;
+
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ // We know that val64 is holding up to 18 digits. Break it into two
+ // eight-digit places that can each go into a val23
+ left.start = combined.start;
+ left.run = combined.run - 4;
+ left.val32 = combined.val64 / 100000000;
+
+ right.start = combined.start+left.run;
+ right.run = 4;
+ right.val32 = combined.val64 % 100000000;
+
+ packed_from_combined(left);
+ packed_from_combined(right);
+ break;
+
+ case 9:
+ // We know that val64 is holding 17 or 18 digits. Break off the
+ // bottom eight.
+ left.start = combined.start;
+ left.run = combined.run - 4;
+ left.val64 = combined.val64 / 100000000;
+
+ right.start = combined.start+left.run;
+ right.run = 4;
+ right.val32 = combined.val64 % 100000000;
+
+ packed_from_combined(left);
+ packed_from_combined(right);
+ break;
+
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ // We know that val64 is holding between 18 and 36 digits. Break it
+ // two val64:
+
+ left.start = combined.start;
+ left.run = combined.run - 9;
+ left.val64 = combined.val128 / 1000000000000000000ULL;
+
+ right.start = combined.start+left.run;
+ right.run = 9;
+ right.val64 = combined.val128 % 1000000000000000000ULL;
+
+ packed_from_combined(left);
+ packed_from_combined(right);
+ break;
+
+ default:
+ // For twenty or more digits we peel eighteen digits at a time off the
+ // right side:
+ left.start = combined.start;
+ left.run = combined.run - 9;
+ left.val128 = combined.val128 / 1000000000000000000ULL;
+
+ right.start = combined.start+left.run;
+ right.run = 9;
+ right.val64 = combined.val128 % 1000000000000000000ULL;
+
+ packed_from_combined(left);
+ packed_from_combined(right);
+ break;
+ }
+ }
+
+extern "C"
+void
+__gg__binary_to_packed( unsigned char *result,
+ int digits,
+ __int128 value)
+ {
+ size_t length = (digits+1)/2;
+
+ COMBINED combined;
+ combined.start = 0;
+ combined.run = length;
+ combined.val128 = value;
+ packed_from_combined(combined);
+ memcpy(result, combined_string, length);
+ }
diff --git a/libgcobol/stringbin.h b/libgcobol/stringbin.h
index 0276704..5ddb441 100644
--- a/libgcobol/stringbin.h
+++ b/libgcobol/stringbin.h
@@ -39,4 +39,9 @@ bool __gg__binary_to_string_internal( char *result,
int digits,
__int128 value);
+extern "C"
+void __gg__binary_to_packed( unsigned char *result,
+ int digits,
+ __int128 value);
+
#endif