aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaius Mulley <gaius.mulley@southwales.ac.uk>2022-04-29 11:23:12 +0100
committerGaius Mulley <gaius.mulley@southwales.ac.uk>2022-04-29 11:23:12 +0100
commit955517d6fe442493d35ba4a477b7f523f73db2d9 (patch)
tree51d9cec39edf09efb3e7d8ea228a942382db6e3b
parentcf78131316dc9abbcbb6477233d84c23b01888d7 (diff)
parent44b09adb9bad99dd7e3017c5ecefed7f7c9a1590 (diff)
downloadgcc-955517d6fe442493d35ba4a477b7f523f73db2d9.zip
gcc-955517d6fe442493d35ba4a477b7f523f73db2d9.tar.gz
gcc-955517d6fe442493d35ba4a477b7f523f73db2d9.tar.bz2
Merge branch 'master' into devel/modula-2.
-rw-r--r--contrib/ChangeLog5
-rwxr-xr-xcontrib/gcc-changelog/git_update_version.py2
-rw-r--r--gcc/BASE-VER2
-rw-r--r--gcc/ChangeLog118
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/gnatvsn.ads2
-rw-r--r--gcc/analyzer/ChangeLog23
-rw-r--r--gcc/analyzer/diagnostic-manager.cc24
-rw-r--r--gcc/analyzer/engine.cc9
-rw-r--r--gcc/analyzer/exploded-graph.h2
-rw-r--r--gcc/analyzer/feasible-graph.cc65
-rw-r--r--gcc/analyzer/feasible-graph.h6
-rw-r--r--gcc/analyzer/program-point.cc4
-rw-r--r--gcc/analyzer/program-point.h1
-rw-r--r--gcc/analyzer/store.cc12
-rw-r--r--gcc/cgraph.cc6
-rw-r--r--gcc/config/i386/i386-expand.cc3
-rw-r--r--gcc/cp/ChangeLog42
-rw-r--r--gcc/cp/call.cc13
-rw-r--r--gcc/cp/coroutines.cc14
-rw-r--r--gcc/cp/pt.cc3
-rw-r--r--gcc/cp/rtti.cc15
-rw-r--r--gcc/cp/semantics.cc25
-rw-r--r--gcc/d/ChangeLog6
-rw-r--r--gcc/doc/gcov-tool.texi36
-rw-r--r--gcc/doc/gcov.texi389
-rw-r--r--gcc/doc/invoke.texi35
-rw-r--r--gcc/fortran/ChangeLog5
-rw-r--r--gcc/fortran/gfortran.texi30
-rw-r--r--gcc/fortran/invoke.texi18
-rw-r--r--gcc/gcov-io.cc79
-rw-r--r--gcc/gcov-io.h35
-rw-r--r--gcc/gcov-tool.cc107
-rw-r--r--gcc/gimple-fold.cc2
-rw-r--r--gcc/gimple-range-cache.h6
-rw-r--r--gcc/gimple-range-fold.cc6
-rw-r--r--gcc/gimple-ssa-evrp-analyze.cc6
-rw-r--r--gcc/gimple-ssa-sprintf.cc3
-rw-r--r--gcc/ipa-cp.cc2
-rw-r--r--gcc/ipa-prop.cc12
-rw-r--r--gcc/range-op.cc140
-rw-r--r--gcc/range-op.h72
-rw-r--r--gcc/range.h28
-rw-r--r--gcc/testsuite/ChangeLog87
-rw-r--r--gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C24
-rw-r--r--gcc/testsuite/g++.dg/lto/pr105399_0.C9
-rw-r--r--gcc/testsuite/g++.dg/rtti/typeid-complete1.C14
-rw-r--r--gcc/testsuite/g++.dg/template/partial-specialization13.C11
-rw-r--r--gcc/testsuite/g++.dg/warn/Wparentheses-31.C59
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/symbolic-12.c106
-rw-r--r--gcc/testsuite/gcc.dg/gcov-info-to-gcda.c36
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr94157_0.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr105376.c9
-rw-r--r--gcc/testsuite/lib/prune.exp5
-rw-r--r--gcc/tree-inline.cc6
-rw-r--r--gcc/tree-ssa-copy.cc4
-rw-r--r--gcc/tree-ssa-dom.cc2
-rw-r--r--gcc/tree-ssa-math-opts.cc15
-rw-r--r--gcc/tree-ssa-phiopt.cc4
-rw-r--r--gcc/tree-ssa-pre.cc13
-rw-r--r--gcc/tree-ssa-sccvn.cc4
-rw-r--r--gcc/tree-ssa-strlen.cc8
-rw-r--r--gcc/tree-ssanames.cc12
-rw-r--r--gcc/tree-ssanames.h5
-rw-r--r--gcc/tree-vect-loop-manip.cc41
-rw-r--r--gcc/tree-vect-loop.cc7
-rw-r--r--gcc/tree-vrp.cc21
-rw-r--r--gcc/tree.cc21
-rw-r--r--gcc/value-range-equiv.cc4
-rw-r--r--gcc/value-range-equiv.h4
-rw-r--r--gcc/value-range.cc4
-rw-r--r--gcc/value-range.h13
-rw-r--r--gcc/vr-values.cc21
-rw-r--r--libgcc/ChangeLog65
-rw-r--r--libgcc/gcov.h17
-rw-r--r--libgcc/libgcov-driver-system.c7
-rw-r--r--libgcc/libgcov-driver.c44
-rw-r--r--libgcc/libgcov-util.c150
-rw-r--r--libgcc/libgcov.h3
-rw-r--r--libgomp/ChangeLog7
-rw-r--r--libphobos/ChangeLog4
-rw-r--r--libstdc++-v3/ChangeLog16
-rw-r--r--maintainer-scripts/ChangeLog5
-rw-r--r--maintainer-scripts/crontab9
84 files changed, 1939 insertions, 374 deletions
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index c35edcc..cfacc18 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,8 @@
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc-changelog/git_update_version.py (active_refs): Add
+ releases/gcc-12.
+
2022-04-25 Martin Liska <mliska@suse.cz>
* filter-clang-warnings.py: Filter out
diff --git a/contrib/gcc-changelog/git_update_version.py b/contrib/gcc-changelog/git_update_version.py
index 2de9688..259dd4e 100755
--- a/contrib/gcc-changelog/git_update_version.py
+++ b/contrib/gcc-changelog/git_update_version.py
@@ -63,7 +63,7 @@ def prepend_to_changelog_files(repo, folder, git_commit, add_to_git):
active_refs = ['master', 'releases/gcc-9', 'releases/gcc-10',
- 'releases/gcc-11']
+ 'releases/gcc-11', 'releases/gcc-12']
parser = argparse.ArgumentParser(description='Update DATESTAMP and generate '
'ChangeLog entries')
diff --git a/gcc/BASE-VER b/gcc/BASE-VER
index b700dc1..02161ca 100644
--- a/gcc/BASE-VER
+++ b/gcc/BASE-VER
@@ -1 +1 @@
-12.0.1
+13.0.0
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a93b56c..1599c45 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,121 @@
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * doc/gcov.texi (Profiling and Test Coverage in Freestanding
+ Environments): New section.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * doc/gcov-tool.texi: Document merge-stream subcommand.
+ * doc/invoke.texi (fprofile-info-section): Mention merge-stream
+ subcommand of gcov-tool.
+ * gcov-tool.cc (gcov_profile_merge_stream): Declare.
+ (print_merge_stream_usage_message): New.
+ (merge_stream_usage): Likewise.
+ (do_merge_stream): Likewise.
+ (print_usage): Call print_merge_stream_usage_message().
+ (main): Call do_merge_stream() to execute merge-stream subcommand.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov-io.cc (gcov_file_error): New enum.
+ (gcov_var): Use gcov_file_error enum for the error member.
+ (gcov_open): Use GCOV_FILE_NO_ERROR.
+ (gcov_close): Use GCOV_FILE_WRITE_ERROR.
+ (gcov_write): Likewise.
+ (gcov_write_unsigned): Likewise.
+ (gcov_write_string): Likewise.
+ (gcov_read_bytes): Set error code if EOF is reached.
+ (gcov_read_counter): Use GCOV_FILE_COUNTER_OVERFLOW.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov-io.cc (GCOV_MODE_STDIN): Define.
+ (gcov_position): For gcov-tool, return calculated position if file is
+ stdin.
+ (gcov_open): For gcov-tool, use stdin if filename is NULL.
+ (gcov_close): For gcov-tool, do not close stdin.
+ (gcov_read_bytes): For gcov-tool, update position if file is stdin.
+ (gcov_sync): For gcov-tool, discard input if file is stdin.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * doc/invoke.texi (fprofile-info-section): Mention
+ __gcov_filename_to_gcfn(). Use "freestanding" to match with C11
+ standard language. Fix minor example code issues.
+ * gcov-io.h (GCOV_FILENAME_MAGIC): Define and document.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov-io.cc (gcov_seek): Make it static.
+ * gcov-io.h (struct gcov_summary): Do not mention gcov_seek().
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov-tool.cc (gcov_do_dump): Add mode parameter.
+ (gcov_output_files): Open files for reading and writing.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov-io.cc (gcov_open): Always use the mode parameter.
+ * gcov-io.h (gcov_open): Declare it unconditionally.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov-tool.cc (gcov_profile_merge): Adjust return type.
+ (profile_merge): Allow merging of directories which contain no profile
+ files.
+
+2022-04-28 David Malcolm <dmalcolm@redhat.com>
+
+ * doc/invoke.texi (-fdump-analyzer-feasibility): Mention the
+ fpath.txt output.
+
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386-expand.cc (ix86_expand_int_movcc): Create a
+ temporary only if out overlaps compare_op, not when it overlaps
+ op0 or op1.
+
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR lto/105399
+ * cgraph.cc (cgraph_node::verify_node): Don't verify
+ semantic_interposition flag against
+ opt_for_fn (decl, flag_semantic_interposition) for aliases in lto1.
+
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/105331
+ * config/i386/i386.cc (ix86_gimplify_va_arg): Mark va_arg_tmp
+ temporary TREE_ADDRESSABLE before trying to gimplify ADDR_EXPR
+ of it.
+
+2022-04-28 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/install.texi (Configuration): Remove misleading text
+ around LE PowerPC Linux multilibs.
+
+2022-04-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR d/103528
+ * doc/install.texi (Tools/packages necessary for building GCC)
+ (GDC): Document libphobos requirement.
+ (Host/target specific installation notes for GCC, *-*-solaris2*):
+ Document libphobos and GDC specifics.
+
+2022-04-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/105219
+ * tree-vect-loop.cc (vect_transform_loop): Disable
+ special code narrowing the vectorized epilogue max
+ iterations when peeling for alignment or gaps was in effect.
+
+2022-04-28 Xi Ruoyao <xry111@mengyan1223.wang>
+
+ * config/loongarch/loongarch.cc
+ (loongarch_flatten_aggregate_field): Ignore empty fields for
+ RECORD_TYPE.
+
2022-04-27 Lulu Cheng <chenglulu@loongson.cn>
* config/loongarch/loongarch.md: Add fdiv define_expand template,
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 04ee20d..4041ef7 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20220428
+20220429
diff --git a/gcc/ada/gnatvsn.ads b/gcc/ada/gnatvsn.ads
index 47a06b9..311a103 100644
--- a/gcc/ada/gnatvsn.ads
+++ b/gcc/ada/gnatvsn.ads
@@ -32,7 +32,7 @@ package Gnatvsn is
-- Static string identifying this version, that can be used as an argument
-- to e.g. pragma Ident.
- Library_Version : constant String := "12";
+ Library_Version : constant String := "13";
-- Library version. It needs to be updated whenever the major version
-- number is changed.
--
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 9ab6169..f406960 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,26 @@
+2022-04-28 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/105285
+ * store.cc (binding_cluster::get_any_binding): Handle accessing
+ sub_svalues of clusters where the base region has a symbolic
+ binding.
+
+2022-04-28 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-manager.cc (epath_finder::process_worklist_item):
+ Call dump_feasible_path when a path that reaches the the target
+ enode is found.
+ (epath_finder::dump_feasible_path): New.
+ * engine.cc (feasibility_state::dump_to_pp): New.
+ * exploded-graph.h (feasibility_state::dump_to_pp): New decl.
+ * feasible-graph.cc (feasible_graph::dump_feasible_path): New.
+ * feasible-graph.h (feasible_graph::dump_feasible_path): New
+ decls.
+ * program-point.cc (function_point::print): Fix missing trailing
+ newlines.
+ * program-point.h (program_point::print_source_line): Remove
+ unimplemented decl.
+
2022-04-25 David Malcolm <dmalcolm@redhat.com>
PR analyzer/105365
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index bf7c8fc..5bd4cd4 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -112,6 +112,10 @@ private:
void dump_feasible_graph (const exploded_node *target_enode,
const char *desc, unsigned diag_idx,
const feasible_graph &fg);
+ void dump_feasible_path (const exploded_node *target_enode,
+ unsigned diag_idx,
+ const feasible_graph &fg,
+ const feasible_node &fnode) const;
const exploded_graph &m_eg;
shortest_exploded_paths *m_sep;
@@ -510,6 +514,9 @@ epath_finder::process_worklist_item (feasible_worklist *worklist,
target_enode->m_index, diag_idx,
succ_fnode->get_path_length ());
*out_best_path = fg->make_epath (succ_fnode);
+ if (flag_dump_analyzer_feasibility)
+ dump_feasible_path (target_enode, diag_idx, *fg, *succ_fnode);
+
/* Success: stop the worklist iteration. */
return false;
}
@@ -608,6 +615,23 @@ epath_finder::dump_feasible_graph (const exploded_node *target_enode,
free (filename);
}
+/* Dump the path to FNODE to "BASE_NAME.DIAG_IDX.to-enN.fpath.txt". */
+
+void
+epath_finder::dump_feasible_path (const exploded_node *target_enode,
+ unsigned diag_idx,
+ const feasible_graph &fg,
+ const feasible_node &fnode) const
+{
+ auto_timevar tv (TV_ANALYZER_DUMP);
+ pretty_printer pp;
+ pp_printf (&pp, "%s.%i.to-en%i.fpath.txt",
+ dump_base_name, diag_idx, target_enode->m_index);
+ char *filename = xstrdup (pp_formatted_text (&pp));
+ fg.dump_feasible_path (fnode, filename);
+ free (filename);
+}
+
/* class saved_diagnostic. */
/* saved_diagnostic's ctor.
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index d8b6195..e43406e 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -4605,6 +4605,15 @@ feasibility_state::maybe_update_for_edge (logger *logger,
return true;
}
+/* Dump this object to PP. */
+
+void
+feasibility_state::dump_to_pp (pretty_printer *pp,
+ bool simple, bool multiline) const
+{
+ m_model.dump_to_pp (pp, simple, multiline);
+}
+
/* A family of cluster subclasses for use when generating .dot output for
exploded graphs (-fdump-analyzer-exploded-graph), for grouping the
enodes into hierarchical boxes.
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index af0ab8d..2dcdcc5 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -1001,6 +1001,8 @@ public:
const region_model &get_model () const { return m_model; }
const auto_sbitmap &get_snodes_visited () const { return m_snodes_visited; }
+ void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
+
private:
region_model m_model;
auto_sbitmap m_snodes_visited;
diff --git a/gcc/analyzer/feasible-graph.cc b/gcc/analyzer/feasible-graph.cc
index 0ac8484..fe7e79f 100644
--- a/gcc/analyzer/feasible-graph.cc
+++ b/gcc/analyzer/feasible-graph.cc
@@ -218,6 +218,71 @@ feasible_graph::make_epath (feasible_node *fnode) const
return epath;
}
+/* Dump the path to DST_FNODE in textual form to PP. */
+
+void
+feasible_graph::dump_feasible_path (const feasible_node &dst_fnode,
+ pretty_printer *pp) const
+{
+ const feasible_node *fnode = &dst_fnode;
+
+ auto_vec<const feasible_edge *> fpath;
+
+ /* FG is actually a tree. Built the path backwards, by walking
+ backwards from FNODE until we reach the origin. */
+ while (fnode->get_inner_node ()->m_index != 0)
+ {
+ gcc_assert (fnode->m_preds.length () == 1);
+ feasible_edge *pred_fedge
+ = static_cast <feasible_edge *> (fnode->m_preds[0]);
+ fpath.safe_push (pred_fedge);
+ fnode = static_cast <const feasible_node *> (pred_fedge->m_src);
+ }
+
+ /* Now reverse it. */
+ fpath.reverse ();
+
+ for (unsigned i = 0; i < fpath.length (); i++)
+ {
+ const feasible_edge *fedge = fpath[i];
+ const feasible_node *src_fnode
+ = static_cast <const feasible_node *> (fedge->m_src);
+ const feasible_node *dest_fnode
+ = static_cast <const feasible_node *> (fedge->m_dest);
+
+ pp_printf (pp, "fpath[%i]: FN %i (EN %i) -> FN %i (EN %i)",
+ i,
+ src_fnode->get_index (),
+ src_fnode->get_inner_node ()->m_index,
+ dest_fnode->get_index (),
+ dest_fnode->get_inner_node ()->m_index);
+ pp_newline (pp);
+ pp_printf (pp, " FN %i (EN %i):",
+ dest_fnode->get_index (),
+ dest_fnode->get_inner_node ()->m_index);
+ pp_newline (pp);
+ const program_point &point = dest_fnode->get_inner_node ()->get_point ();
+ point.print (pp, format (true));
+ dest_fnode->get_state ().dump_to_pp (pp, true, true);
+ pp_newline (pp);
+ }
+}
+
+/* Dump the path to DST_FNODE in textual form to FILENAME. */
+
+void
+feasible_graph::dump_feasible_path (const feasible_node &dst_fnode,
+ const char *filename) const
+{
+ FILE *fp = fopen (filename, "w");
+ pretty_printer pp;
+ pp_format_decoder (&pp) = default_tree_printer;
+ pp.buffer->stream = fp;
+ dump_feasible_path (dst_fnode, &pp);
+ pp_flush (&pp);
+ fclose (fp);
+}
+
/* Dump stats about this graph to LOGGER. */
void
diff --git a/gcc/analyzer/feasible-graph.h b/gcc/analyzer/feasible-graph.h
index d10a28d..f1868af 100644
--- a/gcc/analyzer/feasible-graph.h
+++ b/gcc/analyzer/feasible-graph.h
@@ -197,11 +197,17 @@ class feasible_graph : public digraph <fg_traits>
exploded_path *make_epath (feasible_node *fnode) const;
+ void dump_feasible_path (const feasible_node &dst_fnode,
+ const char *filename) const;
+
unsigned get_num_infeasible () const { return m_num_infeasible; }
void log_stats (logger *logger) const;
private:
+ void dump_feasible_path (const feasible_node &dst_fnode,
+ pretty_printer *pp) const;
+
unsigned m_num_infeasible;
};
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index 61cea8a..8fa7066 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -114,6 +114,8 @@ function_point::print (pretty_printer *pp, const format &f) const
case PK_ORIGIN:
pp_printf (pp, "origin");
+ if (f.m_newlines)
+ pp_newline (pp);
break;
case PK_BEFORE_SUPERNODE:
@@ -156,6 +158,8 @@ function_point::print (pretty_printer *pp, const format &f) const
case PK_AFTER_SUPERNODE:
pp_printf (pp, "after SN: %i", m_supernode->m_index);
+ if (f.m_newlines)
+ pp_newline (pp);
break;
}
}
diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h
index 4b1c733..6084c9e 100644
--- a/gcc/analyzer/program-point.h
+++ b/gcc/analyzer/program-point.h
@@ -179,7 +179,6 @@ public:
}
void print (pretty_printer *pp, const format &f) const;
- void print_source_line (pretty_printer *pp) const;
void dump () const;
json::object *to_json () const;
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 35f66a4..f5f8fe0 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -1519,6 +1519,18 @@ binding_cluster::get_any_binding (store_manager *mgr,
= get_binding_recursive (mgr, reg))
return direct_sval;
+ /* If we had a write to a cluster of unknown size, we might
+ have a self-binding of the whole base region with an svalue,
+ where the base region is symbolic.
+ Handle such cases by returning sub_svalue instances. */
+ if (const svalue *cluster_sval = maybe_get_simple_value (mgr))
+ {
+ /* Extract child svalue from parent svalue. */
+ region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
+ return rmm_mgr->get_or_create_sub_svalue (reg->get_type (),
+ cluster_sval, reg);
+ }
+
/* If this cluster has been touched by a symbolic write, then the content
of any subregion not currently specifically bound is "UNKNOWN". */
if (m_touched)
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index d3cc06b..0159eaa 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -3488,7 +3488,11 @@ cgraph_node::verify_node (void)
"returns a pointer");
error_found = true;
}
- if (definition && externally_visible
+ if (definition
+ && externally_visible
+ /* For aliases in lto1 free_lang_data doesn't guarantee preservation
+ of opt_for_fn (decl, flag_semantic_interposition). See PR105399. */
+ && (!alias || !in_lto_p)
&& semantic_interposition
!= opt_for_fn (decl, flag_semantic_interposition))
{
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 31780b6..bc806ff 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -3224,8 +3224,7 @@ ix86_expand_int_movcc (rtx operands[])
}
diff = ct - cf;
- if (reg_overlap_mentioned_p (out, op0)
- || reg_overlap_mentioned_p (out, op1))
+ if (reg_overlap_mentioned_p (out, compare_op))
tmp = gen_reg_rtx (mode);
if (mode == DImode)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3ef9e89..6304c14 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,45 @@
+2022-04-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/105425
+ * pt.cc (unify) <case TEMPLATE_PARM_INDEX>: Treat
+ DEPENDENT_OPERATOR_TYPE like an empty type.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/104051
+ * coroutines.cc (coro_diagnose_throwing_final_aw_expr): Handle
+ non-target expression inputs.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/105301
+ * coroutines.cc (coro_promise_type_found_p): Account for possible
+ mutliple overloads of the promise return_value() method.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/105287
+ * coroutines.cc (maybe_promote_temps): Ensure generated temporaries
+ are added to the bind expr.
+ (add_var_to_bind): Fix local var naming to use portable punctuation.
+ (register_local_var_uses): Do not add synthetic names to unnamed
+ temporaries.
+
+2022-04-28 Nathan Sidwell <nathan@acm.org>
+ Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/103868
+ * coroutines.cc (finish_co_await_expr): Do not process non-dependent
+ coroutine expressions at template definition time.
+ (finish_co_yield_expr): Likewise.
+ (finish_co_return_stmt): Likewise.
+
+2022-04-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90107
+ * parser.cc (cp_parser_class_specifier_1): Accept :: after a class
+ definition.
+
2022-04-27 Jason Merrill <jason@redhat.com>
* tree.cc (strip_typedefs): Add default argument comments.
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index fa18d7f..959279d 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -7111,9 +7111,10 @@ extract_call_expr (tree call)
default:;
}
- gcc_assert (TREE_CODE (call) == CALL_EXPR
- || TREE_CODE (call) == AGGR_INIT_EXPR
- || call == error_mark_node);
+ if (TREE_CODE (call) != CALL_EXPR
+ && TREE_CODE (call) != AGGR_INIT_EXPR
+ && call != error_mark_node)
+ return NULL_TREE;
return call;
}
@@ -11180,6 +11181,12 @@ build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args,
*fn_p = fn;
/* Build the actual CALL_EXPR. */
call = build_over_call (cand, flags, complain);
+
+ /* Suppress warnings for if (my_struct.operator= (x)) where
+ my_struct is implicitly converted to bool. */
+ if (TREE_CODE (call) == MODIFY_EXPR)
+ suppress_warning (call, OPT_Wparentheses);
+
/* In an expression of the form `a->f()' where `f' turns
out to be a static member function, `a' is
none-the-less evaluated. */
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 551ddc9..1d886b3 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -3913,6 +3913,7 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
if (TREE_CODE (*stmt) == BIND_EXPR)
{
tree lvar;
+ unsigned serial = 0;
for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
lvar = DECL_CHAIN (lvar))
{
@@ -3973,14 +3974,15 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
else if (lvname != NULL_TREE)
buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname),
lvd->nest_depth, lvd->bind_indx);
+ else
+ buf = xasprintf ("_D%u_%u_%u", lvd->nest_depth, lvd->bind_indx,
+ serial++);
+
/* TODO: Figure out if we should build a local type that has any
excess alignment or size from the original decl. */
- if (buf)
- {
- local_var.field_id = coro_make_frame_entry (lvd->field_list, buf,
- lvtype, lvd->loc);
- free (buf);
- }
+ local_var.field_id = coro_make_frame_entry (lvd->field_list, buf,
+ lvtype, lvd->loc);
+ free (buf);
/* We don't walk any of the local var sub-trees, they won't contain
any bind exprs. */
}
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e785c5d..81f7ef5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24276,7 +24276,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
}
}
- if (!TREE_TYPE (arg))
+ if (!TREE_TYPE (arg)
+ || TREE_CODE (TREE_TYPE (arg)) == DEPENDENT_OPERATOR_TYPE)
/* Template-parameter dependent expression. Just accept it for now.
It will later be processed in convert_template_argument. */
;
diff --git a/gcc/cp/rtti.cc b/gcc/cp/rtti.cc
index a4dedc3..f5b43ec 100644
--- a/gcc/cp/rtti.cc
+++ b/gcc/cp/rtti.cc
@@ -446,9 +446,6 @@ get_tinfo_decl_direct (tree type, tree name, int pseudo_ix)
gcc_checking_assert (TREE_CODE (type) != METHOD_TYPE);
- if (pseudo_ix < 0)
- type = complete_type (type);
-
if (CLASS_TYPE_P (type))
d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
@@ -1693,7 +1690,17 @@ emit_tinfo_decl (tree decl)
tree init;
DECL_EXTERNAL (decl) = 0;
- init = get_pseudo_ti_init (type, get_pseudo_ti_index (type));
+ int pseudo_ix = get_pseudo_ti_index (type);
+ const tinfo_s *ti = get_tinfo_desc (pseudo_ix);
+ if (TREE_TYPE (decl) != ti->type)
+ {
+ /* If the class became complete since we first called get_tinfo_decl,
+ its type_info descriptor may have switched from __class_type_info
+ to e.g. __si_class_type_info. */
+ TREE_TYPE (decl) = ti->type;
+ relayout_decl (decl);
+ }
+ init = get_pseudo_ti_init (type, pseudo_ix);
DECL_INITIAL (decl) = init;
mark_used (decl);
cp_finish_decl (decl, init, false, NULL_TREE, 0);
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ab48f11..377f611 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -826,6 +826,26 @@ finish_goto_stmt (tree destination)
return add_stmt (build_stmt (input_location, GOTO_EXPR, destination));
}
+/* Returns true if CALL is a (possibly wrapped) CALL_EXPR or AGGR_INIT_EXPR
+ to operator= () that is written as an operator expression. */
+static bool
+is_assignment_op_expr_p (tree call)
+{
+ if (call == NULL_TREE)
+ return false;
+
+ call = extract_call_expr (call);
+ if (call == NULL_TREE
+ || call == error_mark_node
+ || !CALL_EXPR_OPERATOR_SYNTAX (call))
+ return false;
+
+ tree fndecl = cp_get_callee_fndecl_nofold (call);
+ return fndecl != NULL_TREE
+ && DECL_ASSIGNMENT_OPERATOR_P (fndecl)
+ && DECL_OVERLOADED_OPERATOR_IS (fndecl, NOP_EXPR);
+}
+
/* COND is the condition-expression for an if, while, etc.,
statement. Convert it to a boolean value, if appropriate.
In addition, verify sequence points if -Wsequence-point is enabled. */
@@ -847,7 +867,7 @@ maybe_convert_cond (tree cond)
/* Do the conversion. */
cond = convert_from_reference (cond);
- if (TREE_CODE (cond) == MODIFY_EXPR
+ if ((TREE_CODE (cond) == MODIFY_EXPR || is_assignment_op_expr_p (cond))
&& warn_parentheses
&& !warning_suppressed_p (cond, OPT_Wparentheses)
&& warning_at (cp_expr_loc_or_input_loc (cond),
@@ -11958,8 +11978,7 @@ check_trait_type (tree type)
return (check_trait_type (TREE_VALUE (type))
&& check_trait_type (TREE_CHAIN (type)));
- if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
- && COMPLETE_TYPE_P (TREE_TYPE (type)))
+ if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
return true;
if (VOID_TYPE_P (type))
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index bb179bc..546f21c 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,9 @@
+2022-04-28 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * dmd/MERGE: Merge upstream dmd 313d28b3d.
+ * d-port.cc (Port::memicmp): Use d_size_t instead of size_t.
+ (Port::valcpy): Likewise.
+
2022-04-21 Iain Buclaw <ibuclaw@gdcproject.org>
* dmd/MERGE: Merge upstream dmd eb7bee331.
diff --git a/gcc/doc/gcov-tool.texi b/gcc/doc/gcov-tool.texi
index d79dbc9..7715083 100644
--- a/gcc/doc/gcov-tool.texi
+++ b/gcc/doc/gcov-tool.texi
@@ -53,6 +53,10 @@ Current gcov-tool supports the following functionalities:
merge two sets of profiles with weights.
@item
+read a stream of profiles with associated filenames and merge it with a set of
+profiles with weights.
+
+@item
read one set of profile and rewrite profile contents. One can scale or
normalize the count values.
@end itemize
@@ -65,6 +69,12 @@ them. One can specify the weight to factor in the relative importance of
each input.
@item
+Collect profiles from target systems without a filesystem (freestanding
+environments). Merge the collected profiles with associated profiles
+present on the host system. One can specify the weight to factor in the
+relative importance of each input.
+
+@item
Rewrite the profile after removing a subset of the gcda files, while maintaining
the consistency of the summary and the histogram.
@@ -117,6 +127,10 @@ gcov-tool merge [merge-options] @var{directory1} @var{directory2}
[@option{-v}|@option{--verbose}]
[@option{-w}|@option{--weight} @var{w1,w2}]
+gcov-tool merge-stream [merge-stream-options] [@var{file}]
+ [@option{-v}|@option{--verbose}]
+ [@option{-w}|@option{--weight} @var{w1,w2}]
+
gcov-tool rewrite [rewrite-options] @var{directory}
[@option{-n}|@option{--normalize} @var{long_long_value}]
[@option{-o}|@option{--output} @var{directory}]
@@ -169,6 +183,28 @@ Set the merge weights of the @var{directory1} and @var{directory2},
respectively. The default weights are 1 for both.
@end table
+@item merge-stream
+Collect profiles with associated filenames from a @emph{gcfn} and @emph{gcda}
+data stream. Read the stream from the file specified by @var{file} or from
+@file{stdin}. Merge the profiles with associated profiles in the host
+filesystem. Apply the optional weights while merging profiles.
+
+For the generation of a @emph{gcfn} and @emph{gcda} data stream on the target
+system, please have a look at the @code{__gcov_filename_to_gcfn()} and
+@code{__gcov_info_to_gcda()} functions declared in @code{#include <gcov.h>}.
+@table @gcctabopt
+
+@item -v
+@itemx --verbose
+Set the verbose mode.
+
+@item -w @var{w1},@var{w2}
+@itemx --weight @var{w1},@var{w2}
+Set the merge weights of the profiles from the @emph{gcfn} and @emph{gcda} data
+stream and the associated profiles in the host filesystem, respectively. The
+default weights are 1 for both.
+@end table
+
@item rewrite
Read the specified profile directory and rewrite to a new directory.
@table @gcctabopt
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index fc39da0..a1f7d26 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -41,6 +41,8 @@ test code coverage in your programs.
* Gcov and Optimization:: Using gcov with GCC optimization.
* Gcov Data Files:: The files used by gcov.
* Cross-profiling:: Data file relocation.
+* Freestanding Environments:: How to use profiling and test
+ coverage in freestanding environments.
@end menu
@node Gcov Intro
@@ -971,3 +973,390 @@ setting will name the data file @file{/target/run/build/foo.gcda}.
You must move the data files to the expected directory tree in order to
use them for profile directed optimizations (@option{-fprofile-use}), or to
use the @command{gcov} tool.
+
+@node Freestanding Environments
+@section Profiling and Test Coverage in Freestanding Environments
+
+In case your application runs in a hosted environment such as GNU/Linux, then
+this section is likely not relevant to you. This section is intended for
+application developers targeting freestanding environments (for example
+embedded systems) with limited resources. In particular, systems or test cases
+which do not support constructors/destructors or the C library file I/O. In
+this section, the @dfn{target system} runs your application instrumented for
+profiling or test coverage. You develop and analyze your application on the
+@dfn{host system}. We now provide an overview how profiling and test coverage
+can be obtained in this scenario followed by a tutorial which can be exercised
+on the host system. Finally, some system initialization caveats are listed.
+
+@subsection Overview
+
+For an application instrumented for profiling or test coverage, the compiler
+generates some global data structures which are updated by instrumentation code
+while the application runs. These data structures are called the @dfn{gcov
+information}. Normally, when the application exits, the gcov information is
+stored to @file{.gcda} files. There is one file per translation unit
+instrumented for profiling or test coverage. The function
+@code{__gcov_exit()}, which stores the gcov information to a file, is called by
+a global destructor function for each translation unit instrumented for
+profiling or test coverage. It runs at process exit. In a global constructor
+function, the @code{__gcov_init()} function is called to register the gcov
+information of a translation unit in a global list. In some situations, this
+procedure does not work. Firstly, if you want to profile the global
+constructor or exit processing of an operating system, the compiler generated
+functions may conflict with the test objectives. Secondly, you may want to
+test early parts of the system initialization or abnormal program behaviour
+which do not allow a global constructor or exit processing. Thirdly, you need
+a filesystem to store the files.
+
+The @option{-fprofile-info-section} GCC option enables you to use profiling and
+test coverage in freestanding environments. This option disables the use of
+global constructors and destructors for the gcov information. Instead, a
+pointer to the gcov information is stored in a special linker input section for
+each translation unit which is compiled with this option. By default, the
+section name is @code{.gcov_info}. The gcov information is statically
+initialized. The pointers to the gcov information from all translation units
+of an executable can be collected by the linker in a contiguous memory block.
+For the GNU linker, the below linker script output section definition can be
+used to achieve this:
+
+@smallexample
+ .gcov_info :
+ @{
+ PROVIDE (__gcov_info_start = .);
+ KEEP (*(.gcov_info))
+ PROVIDE (__gcov_info_end = .);
+ @}
+@end smallexample
+
+The linker will provide two global symbols, @code{__gcov_info_start} and
+@code{__gcov_info_end}, which define the start and end of the array of pointers
+to gcov information blocks, respectively. The @code{KEEP ()} directive is
+required to prevent a garbage collection of the pointers. They are not
+directly referenced by anything in the executable. The section may be placed
+in a read-only memory area.
+
+In order to transfer the profiling and test coverage data from the target to
+the host system, the application has to provide a function to produce a
+reliable in order byte stream from the target to the host. The byte stream may
+be compressed and encoded using error detection and correction codes to meet
+application-specific requirements. The GCC provided @file{libgcov} target
+library provides two functions, @code{__gcov_info_to_gcda()} and
+@code{__gcov_filename_to_gcfn()}, to generate a byte stream from a gcov
+information bock. The functions are declared in @code{#include <gcov.h>}. The
+byte stream can be deserialized by the @command{merge-stream} subcommand of the
+@command{gcov-tool} to create or update @file{.gcda} files in the host
+filesystem for the instrumented application.
+
+@subsection Tutorial
+
+This tutorial should be exercised on the host system. We will build a program
+instrumented for test coverage. The program runs an application and dumps the
+gcov information to @file{stderr} encoded as a printable character stream. The
+application simply decodes such character streams from @file{stdin} and writes
+the decoded character stream to @file{stdout} (warning: this is binary data).
+The decoded character stream is consumed by the @command{merge-stream}
+subcommand of the @command{gcov-tool} to create or update the @file{.gcda}
+files.
+
+To get started, create an empty directory. Change into the new directory.
+Then you will create the following three files in this directory
+
+@enumerate
+@item
+@file{app.h} - a header file included by @file{app.c} and @file{main.c},
+
+@item
+@file{app.c} - a source file which contains an example application, and
+
+@item
+@file{main.c} - a source file which contains the program main function and code
+to dump the gcov information.
+@end enumerate
+
+Firstly, create the header file @file{app.h} with the following content:
+
+@smallexample
+static const unsigned char a = 'a';
+
+static inline unsigned char *
+encode (unsigned char c, unsigned char buf[2])
+@{
+ buf[0] = c % 16 + a;
+ buf[1] = (c / 16) % 16 + a;
+ return buf;
+@}
+
+extern void application (void);
+@end smallexample
+
+Secondly, create the source file @file{app.c} with the following content:
+
+@smallexample
+#include "app.h"
+
+#include <stdio.h>
+
+/* The application reads a character stream encoded by encode() from stdin,
+ decodes it, and writes the decoded characters to stdout. Characters other
+ than the 16 characters 'a' to 'p' are ignored. */
+
+static int can_decode (unsigned char c)
+@{
+ return (unsigned char)(c - a) < 16;
+@}
+
+void
+application (void)
+@{
+ int first = 1;
+ int i;
+ unsigned char c;
+
+ while ((i = fgetc (stdin)) != EOF)
+ @{
+ unsigned char x = (unsigned char)i;
+
+ if (can_decode (x))
+ @{
+ if (first)
+ c = x - a;
+ else
+ fputc (c + 16 * (x - a), stdout);
+ first = !first;
+ @}
+ else
+ first = 1;
+ @}
+@}
+@end smallexample
+
+Thirdly, create the source file @file{main.c} with the following content:
+
+@smallexample
+#include "app.h"
+
+#include <gcov.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* The start and end symbols are provided by the linker script. We use the
+ array notation to avoid issues with a potential small-data area. */
+
+extern const struct gcov_info *const __gcov_info_start[];
+extern const struct gcov_info *const __gcov_info_end[];
+
+/* This function shall produce a reliable in order byte stream to transfer the
+ gcov information from the target to the host system. */
+
+static void
+dump (const void *d, unsigned n, void *arg)
+@{
+ (void)arg;
+ const unsigned char *c = d;
+ unsigned char buf[2];
+
+ for (unsigned i = 0; i < n; ++i)
+ fwrite (encode (c[i], buf), sizeof (buf), 1, stderr);
+@}
+
+/* The filename is serialized to a gcfn data stream by the
+ __gcov_filename_to_gcfn() function. The gcfn data is used by the
+ "merge-stream" subcommand of the "gcov-tool" to figure out the filename
+ associated with the gcov information. */
+
+static void
+filename (const char *f, void *arg)
+@{
+ __gcov_filename_to_gcfn (f, dump, arg);
+@}
+
+/* The __gcov_info_to_gcda() function may have to allocate memory under
+ certain conditions. Simply try it out if it is needed for your application
+ or not. */
+
+static void *
+allocate (unsigned length, void *arg)
+@{
+ (void)arg;
+ return malloc (length);
+@}
+
+/* Dump the gcov information of all translation units. */
+
+static void
+dump_gcov_info (void)
+@{
+ const struct gcov_info *const *info = __gcov_info_start;
+ const struct gcov_info *const *end = __gcov_info_end;
+
+ /* Obfuscate variable to prevent compiler optimizations. */
+ __asm__ ("" : "+r" (info));
+
+ while (info != end)
+ @{
+ void *arg = NULL;
+ __gcov_info_to_gcda (*info, filename, dump, allocate, arg);
+ fputc ('\n', stderr);
+ ++info;
+ @}
+@}
+
+/* The main() function just runs the application and then dumps the gcov
+ information to stderr. */
+
+int
+main (void)
+@{
+ application ();
+ dump_gcov_info ();
+ return 0;
+@}
+@end smallexample
+
+If we compile @file{app.c} with test coverage and no extra profiling options,
+then a global constructor (@code{_sub_I_00100_0} here, it may have a different
+name in your environment) and destructor (@code{_sub_D_00100_1}) is used to
+register and dump the gcov information, respectively. We also see undefined
+references to @code{__gcov_init} and @code{__gcov_exit}:
+
+@smallexample
+$ gcc --coverage -c app.c
+$ nm app.o
+0000000000000000 r a
+0000000000000030 T application
+0000000000000000 t can_decode
+ U fgetc
+ U fputc
+0000000000000000 b __gcov0.application
+0000000000000038 b __gcov0.can_decode
+0000000000000000 d __gcov_.application
+00000000000000c0 d __gcov_.can_decode
+ U __gcov_exit
+ U __gcov_init
+ U __gcov_merge_add
+ U stdin
+ U stdout
+0000000000000161 t _sub_D_00100_1
+0000000000000151 t _sub_I_00100_0
+@end smallexample
+
+Compile @file{app.c} and @file{main.c} with test coverage and
+@option{-fprofile-info-section}. Now, a read-only pointer size object is
+present in the @code{.gcov_info} section and there are no undefined references
+to @code{__gcov_init} and @code{__gcov_exit}:
+
+@smallexample
+$ gcc --coverage -fprofile-info-section -c main.c
+$ gcc --coverage -fprofile-info-section -c app.c
+$ objdump -h app.o
+
+app.o: file format elf64-x86-64
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 .text 00000151 0000000000000000 0000000000000000 00000040 2**0
+ CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
+ 1 .data 00000100 0000000000000000 0000000000000000 000001a0 2**5
+ CONTENTS, ALLOC, LOAD, RELOC, DATA
+ 2 .bss 00000040 0000000000000000 0000000000000000 000002a0 2**5
+ ALLOC
+ 3 .rodata 0000003c 0000000000000000 0000000000000000 000002a0 2**3
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+ 4 .gcov_info 00000008 0000000000000000 0000000000000000 000002e0 2**3
+ CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 5 .comment 0000004e 0000000000000000 0000000000000000 000002e8 2**0
+ CONTENTS, READONLY
+ 6 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000336 2**0
+ CONTENTS, READONLY
+ 7 .eh_frame 00000058 0000000000000000 0000000000000000 00000338 2**3
+ CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+@end smallexample
+
+We have to customize the program link procedure so that all the
+@code{.gcov_info} linker input sections are placed in a contiguous memory block
+with a begin and end symbol. Firstly, get the default linker script using the
+following commands (we assume a GNU linker):
+
+@smallexample
+$ ld --verbose | sed '1,/^===/d' | sed '/^===/d' > linkcmds
+@end smallexample
+
+Secondly, open the file @file{linkcmds} with a text editor and place the linker
+output section definition from the overview after the @code{.rodata} section
+definition. Link the program executable using the customized linker script:
+
+@smallexample
+$ gcc --coverage main.o app.o -T linkcmds -Wl,-Map,app.map
+@end smallexample
+
+In the linker map file @file{app.map}, we see that the linker placed the
+read-only pointer size objects of our objects files @file{main.o} and
+@file{app.o} into a contiguous memory block and provided the symbols
+@code{__gcov_info_start} and @code{__gcov_info_end}:
+
+@smallexample
+$ grep -C 1 "\.gcov_info" app.map
+
+.gcov_info 0x0000000000403ac0 0x10
+ 0x0000000000403ac0 PROVIDE (__gcov_info_start = .)
+ *(.gcov_info)
+ .gcov_info 0x0000000000403ac0 0x8 main.o
+ .gcov_info 0x0000000000403ac8 0x8 app.o
+ 0x0000000000403ad0 PROVIDE (__gcov_info_end = .)
+@end smallexample
+
+Make sure no @file{.gcda} files are present. Run the program with nothing to
+decode and dump @file{stderr} to the file @file{gcda-0.txt} (first run). Run
+the program to decode @file{gcda-0.txt} and send it to the @command{gcov-tool}
+using the @command{merge-stream} subcommand to create the @file{.gcda} files
+(second run). Run @command{gcov} to produce a report for @file{app.c}. We see
+that the first run with nothing to decode results in a partially covered
+application:
+
+@smallexample
+$ rm -f app.gcda main.gcda
+$ echo "" | ./a.out 2>gcda-0.txt
+$ ./a.out <gcda-0.txt 2>gcda-1.txt | gcov-tool merge-stream
+$ gcov -bc app.c
+File 'app.c'
+Lines executed:69.23% of 13
+Branches executed:66.67% of 6
+Taken at least once:50.00% of 6
+Calls executed:66.67% of 3
+Creating 'app.c.gcov'
+
+Lines executed:69.23% of 13
+@end smallexample
+
+Run the program to decode @file{gcda-1.txt} and send it to the
+@command{gcov-tool} using the @command{merge-stream} subcommand to update the
+@file{.gcda} files. Run @command{gcov} to produce a report for @file{app.c}.
+Since the second run decoded the gcov information of the first run, we have now
+a fully covered application:
+
+@smallexample
+$ ./a.out <gcda-1.txt 2>gcda-2.txt | gcov-tool merge-stream
+$ gcov -bc app.c
+File 'app.c'
+Lines executed:100.00% of 13
+Branches executed:100.00% of 6
+Taken at least once:100.00% of 6
+Calls executed:100.00% of 3
+Creating 'app.c.gcov'
+
+Lines executed:100.00% of 13
+@end smallexample
+
+@subsection System Initialization Caveats
+
+The gcov information of a translation unit consists of several global data
+structures. For example, the instrumented code may update program flow graph
+edge counters in a zero-initialized data structure. It is safe to run
+instrumented code before the zero-initialized data is cleared to zero. The
+coverage information obtained before the zero-initialized data is cleared to
+zero is unusable. Dumping the gcov information using
+@code{__gcov_info_to_gcda()} before the zero-initialized data is cleared to
+zero or the initialized data is loaded, is undefined behaviour. Clearing the
+zero-initialized data to zero through a function instrumented for profiling or
+test coverage is undefined behaviour, since it may produce inconsistent program
+flow graph edge counters for example.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 07b4401..3f4d6f2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -10198,8 +10198,8 @@ diagnostic to @file{@var{file}.@var{idx}.@var{kind}.epath.txt}.
@opindex dump-analyzer-feasibility
Dump internal details about the analyzer's search for feasible paths.
The details are written in a form suitable for viewing with GraphViz
-to filenames of the form @file{@var{file}.*.fg.dot} and
-@file{@var{file}.*.tg.dot}.
+to filenames of the form @file{@var{file}.*.fg.dot},
+@file{@var{file}.*.tg.dot}, and @file{@var{file}.*.fpath.txt}.
@item -fdump-analyzer-json
@opindex fdump-analyzer-json
@@ -15462,7 +15462,7 @@ profile information generated by @option{-fprofile-arcs} is placed in the
specified section for each translation unit. This option disables the profile
information registration through a constructor and it disables the profile
information processing through a destructor. This option is not intended to be
-used in hosted environments such as GNU/Linux. It targets free-standing
+used in hosted environments such as GNU/Linux. It targets freestanding
environments (for example embedded systems) with limited resources which do not
support constructors/destructors or the C library file I/O.
@@ -15487,14 +15487,8 @@ for example like this:
#include <stdio.h>
#include <stdlib.h>
-extern const struct gcov_info *__gcov_info_start[];
-extern const struct gcov_info *__gcov_info_end[];
-
-static void
-filename (const char *f, void *arg)
-@{
- puts (f);
-@}
+extern const struct gcov_info *const __gcov_info_start[];
+extern const struct gcov_info *const __gcov_info_end[];
static void
dump (const void *d, unsigned n, void *arg)
@@ -15505,6 +15499,12 @@ dump (const void *d, unsigned n, void *arg)
printf ("%02x", c[i]);
@}
+static void
+filename (const char *f, void *arg)
+@{
+ __gcov_filename_to_gcfn (f, dump, arg );
+@}
+
static void *
allocate (unsigned length, void *arg)
@{
@@ -15514,8 +15514,8 @@ allocate (unsigned length, void *arg)
static void
dump_gcov_info (void)
@{
- const struct gcov_info **info = __gcov_info_start;
- const struct gcov_info **end = __gcov_info_end;
+ const struct gcov_info *const *info = __gcov_info_start;
+ const struct gcov_info *const *end = __gcov_info_end;
/* Obfuscate variable to prevent compiler optimizations. */
__asm__ ("" : "+r" (info));
@@ -15530,13 +15530,18 @@ dump_gcov_info (void)
@}
int
-main()
+main (void)
@{
- dump_gcov_info();
+ dump_gcov_info ();
return 0;
@}
@end smallexample
+The @command{merge-stream} subcommand of @command{gcov-tool} may be used to
+deserialize the data stream generated by the @code{__gcov_filename_to_gcfn} and
+@code{__gcov_info_to_gcda} functions and merge the profile information into
+@file{.gcda} files on the host filesystem.
+
@item -fprofile-note=@var{path}
@opindex fprofile-note
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 9b6e55a..017f3e6 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,8 @@
+2022-04-28 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran.texi: Mention r16_ieee and r16_ibm.
+ * invoke.texi: Likewise.
+
2022-04-27 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/103662
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index f8737f4..6f622fb 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -589,7 +589,7 @@ Malformed environment variables are silently ignored.
* GFORTRAN_SHOW_LOCUS:: Show location for runtime errors
* GFORTRAN_OPTIONAL_PLUS:: Print leading + where permitted
* GFORTRAN_LIST_SEPARATOR:: Separator for list output
-* GFORTRAN_CONVERT_UNIT:: Set endianness for unformatted I/O
+* GFORTRAN_CONVERT_UNIT:: Set conversion for unformatted I/O
* GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors
* GFORTRAN_FORMATTED_BUFFER_SIZE:: Buffer size for formatted files
* GFORTRAN_UNFORMATTED_BUFFER_SIZE:: Buffer size for unformatted files
@@ -686,11 +686,12 @@ when @command{a.out} is the compiled Fortran program that you want to run.
Default is a single space.
@node GFORTRAN_CONVERT_UNIT
-@section @env{GFORTRAN_CONVERT_UNIT}---Set endianness for unformatted I/O
+@section @env{GFORTRAN_CONVERT_UNIT}---Set conversion for unformatted I/O
By setting the @env{GFORTRAN_CONVERT_UNIT} variable, it is possible
to change the representation of data for unformatted files.
-The syntax for the @env{GFORTRAN_CONVERT_UNIT} variable is:
+The syntax for the @env{GFORTRAN_CONVERT_UNIT} variable for
+most systems is:
@smallexample
GFORTRAN_CONVERT_UNIT: mode | mode ';' exception | exception ;
mode: 'native' | 'swap' | 'big_endian' | 'little_endian' ;
@@ -711,14 +712,24 @@ the modes are the same as for the @code{CONVERT} specifier:
for unformatted files.
@item @code{BIG_ENDIAN} Use the big-endian format for unformatted files.
@end itemize
+For POWER systems which support @option{-mabi=ieeelongdouble},
+there are additional options, which can be combined with the
+others with commas. Those are
+@itemize @w{}
+@item @code{R16_IEEE} Use IEEE 128-bit format for @code{REAL(KIND=16)}.
+@item @code{R16_IBM} Use IBM @code{long double} format for
+@code{REAL(KIND=16)}.
+@end itemize
A missing mode for an exception is taken to mean @code{BIG_ENDIAN}.
Examples of values for @env{GFORTRAN_CONVERT_UNIT} are:
@itemize @w{}
-@item @code{'big_endian'} Do all unformatted I/O in big_endian mode.
+@item @code{'big_endian'} Do all unformatted I/O in big_endian mod.e
@item @code{'little_endian;native:10-20,25'} Do all unformatted I/O
in little_endian mode, except for units 10 to 20 and 25, which are in
native format.
@item @code{'10-20'} Units 10 to 20 are big-endian, the rest is native.
+@item @code{'big_endian,r16_ibm'} Do all unformatted I/O in big-endian
+mode and use IBM long double for output of @code{REAL(KIND=16)} values.
@end itemize
Setting the environment variables should be done on the command
@@ -1736,7 +1747,7 @@ the @code{CONVERT} specifier on the @code{OPEN} statement.
@xref{GFORTRAN_CONVERT_UNIT}, for an alternative way of specifying
the data format via an environment variable.
-Valid values for @code{CONVERT} are:
+Valid values for @code{CONVERT} on most systems are:
@itemize @w{}
@item @code{CONVERT='NATIVE'} Use the native format. This is the default.
@item @code{CONVERT='SWAP'} Swap between little- and big-endian.
@@ -1745,6 +1756,15 @@ for unformatted files.
@item @code{CONVERT='BIG_ENDIAN'} Use the big-endian representation for
unformatted files.
@end itemize
+On POWER systems which support @option{-mabi=ieeelongdouble},
+there are additional options, which can be combined with the others
+with commas. Those are
+@itemize @w{}
+@item @code{CONVERT='R16_IEEE'} Use IEEE 128-bit format for
+@code{REAL(KIND=16)}.
+@item @code{CONVERT='R16_IBM'} Use IBM @code{long double} format for
+real@code{REAL(KIND=16)}.
+@end itemize
Using the option could look like this:
@smallexample
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 5c7501a..c0932f6 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -1435,10 +1435,20 @@ These options affect the runtime behavior of programs compiled with GNU Fortran.
@item -fconvert=@var{conversion}
@opindex @code{fconvert=}@var{conversion}
Specify the representation of data for unformatted files. Valid
-values for conversion are: @samp{native}, the default; @samp{swap},
-swap between big- and little-endian; @samp{big-endian}, use big-endian
-representation for unformatted files; @samp{little-endian}, use little-endian
-representation for unformatted files.
+values for conversion on most systems are: @samp{native}, the default;
+@samp{swap}, swap between big- and little-endian; @samp{big-endian}, use
+big-endian representation for unformatted files; @samp{little-endian}, use
+little-endian representation for unformatted files.
+
+On POWER systems which suppport @option{-mabi=ieeelongdouble},
+there are additional options, which can be combined with others with
+commas. Those are
+@itemize @w{}
+@item @option{-fconvert=r16_ieee} Use IEEE 128-bit format for
+@code{REAL(KIND=16)}.
+@item @option{-fconvert=r16_ibm} Use IBM long double format for
+@code{REAL(KIND=16)}.
+@end itemize
@emph{This option has an effect only when used in the main program.
The @code{CONVERT} specifier and the GFORTRAN_CONVERT_UNIT environment
diff --git a/gcc/gcov-io.cc b/gcc/gcov-io.cc
index 72c40f8..fdf745e 100644
--- a/gcc/gcov-io.cc
+++ b/gcc/gcov-io.cc
@@ -29,14 +29,29 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
static gcov_unsigned_t *gcov_read_words (void *buffer, unsigned);
+/* Indicates the last gcov file access error or that no error occurred
+ so far. */
+enum gcov_file_error
+{
+ GCOV_FILE_COUNTER_OVERFLOW = -1,
+ GCOV_FILE_NO_ERROR = 0,
+ GCOV_FILE_WRITE_ERROR = 1,
+ GCOV_FILE_EOF = 2
+};
+
struct gcov_var
{
FILE *file;
- int error; /* < 0 overflow, > 0 disk error. */
+ enum gcov_file_error error;
int mode; /* < 0 writing, > 0 reading. */
int endian; /* Swap endianness. */
+#ifdef IN_GCOV_TOOL
+ gcov_position_t pos; /* File position for stdin support. */
+#endif
} gcov_var;
+#define GCOV_MODE_STDIN 2
+
/* Save the current position in the gcov file. */
/* We need to expose this function when compiling for gcov-tool. */
#ifndef IN_GCOV_TOOL
@@ -45,6 +60,10 @@ static inline
gcov_position_t
gcov_position (void)
{
+#ifdef IN_GCOV_TOOL
+ if (gcov_var.mode == GCOV_MODE_STDIN)
+ return gcov_var.pos;
+#endif
return ftell (gcov_var.file);
}
@@ -89,15 +108,8 @@ from_file (gcov_unsigned_t value)
Return zero on failure, non-zero on success. */
GCOV_LINKAGE int
-#if IN_LIBGCOV
-gcov_open (const char *name)
-#else
gcov_open (const char *name, int mode)
-#endif
{
-#if IN_LIBGCOV
- int mode = 0;
-#endif
#if GCOV_LOCKED
struct flock s_flock;
int fd;
@@ -111,10 +123,20 @@ gcov_open (const char *name, int mode)
#endif
gcov_nonruntime_assert (!gcov_var.file);
- gcov_var.error = 0;
+ gcov_var.error = GCOV_FILE_NO_ERROR;
#if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
gcov_var.endian = 0;
#endif
+#ifdef IN_GCOV_TOOL
+ gcov_var.pos = 0;
+ if (!name)
+ {
+ gcov_nonruntime_assert (gcov_var.mode > 0);
+ gcov_var.file = stdin;
+ gcov_var.mode = GCOV_MODE_STDIN;
+ return 1;
+ }
+#endif
#if GCOV_LOCKED
if (mode > 0)
{
@@ -197,10 +219,15 @@ gcov_open (const char *name, int mode)
GCOV_LINKAGE int
gcov_close (void)
{
+#ifdef IN_GCOV_TOOL
+ if (gcov_var.file == stdin)
+ gcov_var.file = 0;
+ else
+#endif
if (gcov_var.file)
{
if (fclose (gcov_var.file))
- gcov_var.error = 1;
+ gcov_var.error = GCOV_FILE_WRITE_ERROR;
gcov_var.file = 0;
}
@@ -236,7 +263,7 @@ gcov_write (const void *data, unsigned length)
{
gcov_unsigned_t r = fwrite (data, length, 1, gcov_var.file);
if (r != 1)
- gcov_var.error = 1;
+ gcov_var.error = GCOV_FILE_WRITE_ERROR;
}
/* Write unsigned VALUE to coverage file. */
@@ -246,7 +273,7 @@ gcov_write_unsigned (gcov_unsigned_t value)
{
gcov_unsigned_t r = fwrite (&value, sizeof (value), 1, gcov_var.file);
if (r != 1)
- gcov_var.error = 1;
+ gcov_var.error = GCOV_FILE_WRITE_ERROR;
}
#if !IN_LIBGCOV
@@ -266,7 +293,7 @@ gcov_write_string (const char *string)
{
gcov_unsigned_t r = fwrite (string, length, 1, gcov_var.file);
if (r != 1)
- gcov_var.error = 1;
+ gcov_var.error = GCOV_FILE_WRITE_ERROR;
}
}
#endif
@@ -301,17 +328,15 @@ gcov_write_filename (const char *filename)
gcov_write_string (filename);
}
-#endif
/* Move to a given position in a gcov file. */
-GCOV_LINKAGE void
+static void
gcov_seek (gcov_position_t base)
{
fseek (gcov_var.file, base, SEEK_SET);
}
-#if !IN_LIBGCOV
/* Write a tag TAG and reserve space for the record length. Return a
value to be used for gcov_write_length. */
@@ -370,8 +395,15 @@ gcov_read_bytes (void *buffer, unsigned count)
unsigned read = fread (buffer, count, 1, gcov_var.file);
if (read != 1)
- return NULL;
+ {
+ if (feof (gcov_var.file))
+ gcov_var.error = GCOV_FILE_EOF;
+ return NULL;
+ }
+#ifdef IN_GCOV_TOOL
+ gcov_var.pos += count;
+#endif
return buffer;
}
@@ -416,7 +448,7 @@ gcov_read_counter (void)
if (sizeof (value) > sizeof (gcov_unsigned_t))
value |= ((gcov_type) from_file (buffer[1])) << 32;
else if (buffer[1])
- gcov_var.error = -1;
+ gcov_var.error = GCOV_FILE_COUNTER_OVERFLOW;
return value;
}
@@ -508,6 +540,17 @@ gcov_sync (gcov_position_t base, gcov_unsigned_t length)
{
gcov_nonruntime_assert (gcov_var.mode > 0);
base += length;
+#ifdef IN_GCOV_TOOL
+ if (gcov_var.mode == GCOV_MODE_STDIN)
+ {
+ while (gcov_var.pos < base)
+ {
+ ++gcov_var.pos;
+ (void)fgetc (gcov_var.file);
+ }
+ return;
+ }
+#endif
fseek (gcov_var.file, base, SEEK_SET);
}
#endif
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index 99ce7db..3094763 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -60,14 +60,21 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
file : int32:magic int32:version int32:stamp record*
- The magic ident is different for the notes and the data files. The
- magic ident is used to determine the endianness of the file, when
- reading. The version is the same for both files and is derived
- from gcc's version number. The stamp value is used to synchronize
- note and data files and to synchronize merging within a data
- file. It need not be an absolute time stamp, merely a ticker that
- increments fast enough and cycles slow enough to distinguish
- different compile/run/compile cycles.
+ A filename header may be used to provide a filename for the data in
+ a stream of data to support gcov in freestanding environments. This
+ header is used by the merge-stream subcommand of the gcov-tool. The
+ format of the filename header is
+
+ filename-header : int32:magic int32:version string
+
+ The magic ident is different for the notes and the data files as
+ well as the filename header. The magic ident is used to determine
+ the endianness of the file, when reading. The version is the same
+ for both files and is derived from gcc's version number. The stamp
+ value is used to synchronize note and data files and to synchronize
+ merging within a data file. It need not be an absolute time stamp,
+ merely a ticker that increments fast enough and cycles slow enough
+ to distinguish different compile/run/compile cycles.
Although the ident and version are formally 32 bit numbers, they
are derived from 4 character ASCII strings. The version number
@@ -228,6 +235,7 @@ typedef uint64_t gcov_type_unsigned;
/* File magic. Must not be palindromes. */
#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */
#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */
+#define GCOV_FILENAME_MAGIC ((gcov_unsigned_t)0x6763666e) /* "gcfn" */
#include "version.h"
@@ -340,22 +348,19 @@ struct gcov_summary
/* Functions for reading and writing gcov files. In libgcov you can
open the file for reading then writing. Elsewhere you can open the
file either for reading or for writing. When reading a file you may
- use the gcov_read_* functions, gcov_sync, gcov_position, &
- gcov_error. When writing a file you may use the gcov_write
- functions, gcov_seek & gcov_error. When a file is to be rewritten
+ use the gcov_read_* functions, gcov_sync, gcov_position, and
+ gcov_error. When writing a file you may use the gcov_write*
+ functions and gcov_error. When a file is to be rewritten
you use the functions for reading, then gcov_rewrite then the
functions for writing. Your file may become corrupted if you break
these invariants. */
-#if !IN_LIBGCOV
-GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/);
-#endif
-
#if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t);
#endif
/* Available everywhere. */
+GCOV_LINKAGE int gcov_open (const char *, int) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN;
diff --git a/gcc/gcov-tool.cc b/gcc/gcov-tool.cc
index f4e42ae..ceb2501 100644
--- a/gcc/gcov-tool.cc
+++ b/gcc/gcov-tool.cc
@@ -40,12 +40,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
#include <getopt.h>
-extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int);
+extern struct gcov_info *gcov_profile_merge (struct gcov_info*,
+ struct gcov_info*, int, int);
+extern struct gcov_info *gcov_profile_merge_stream (const char *, int, int);
extern int gcov_profile_overlap (struct gcov_info*, struct gcov_info*);
extern int gcov_profile_normalize (struct gcov_info*, gcov_type);
extern int gcov_profile_scale (struct gcov_info*, float, int, int);
extern struct gcov_info* gcov_read_profile_dir (const char*, int);
-extern void gcov_do_dump (struct gcov_info *, int);
+extern void gcov_do_dump (struct gcov_info *, int, int);
extern const char *gcov_get_filename (struct gcov_info *list);
extern void gcov_set_verbose (void);
@@ -123,7 +125,7 @@ gcov_output_files (const char *out, struct gcov_info *profile)
fatal_error (input_location, "output file %s already exists in folder %s",
filename, out);
- gcov_do_dump (profile, 0);
+ gcov_do_dump (profile, 0, 0);
ret = chdir (pwd);
if (ret)
@@ -141,26 +143,18 @@ profile_merge (const char *d1, const char *d2, const char *out, int w1, int w2)
{
struct gcov_info *d1_profile;
struct gcov_info *d2_profile;
- int ret;
+ struct gcov_info *merged_profile;
d1_profile = gcov_read_profile_dir (d1, 0);
- if (!d1_profile)
- return 1;
+ d2_profile = gcov_read_profile_dir (d2, 0);
- if (d2)
- {
- d2_profile = gcov_read_profile_dir (d2, 0);
- if (!d2_profile)
- return 1;
-
- /* The actual merge: we overwrite to d1_profile. */
- ret = gcov_profile_merge (d1_profile, d2_profile, w1, w2);
-
- if (ret)
- return ret;
- }
+ /* The actual merge: we overwrite to d1_profile. */
+ merged_profile = gcov_profile_merge (d1_profile, d2_profile, w1, w2);
- gcov_output_files (out, d1_profile);
+ if (merged_profile)
+ gcov_output_files (out, merged_profile);
+ else if (verbose)
+ fnotice (stdout, "no profile files were merged\n");
return 0;
}
@@ -236,6 +230,78 @@ do_merge (int argc, char **argv)
return profile_merge (argv[optind], argv[optind+1], output_dir, w1, w2);
}
+/* Usage message for profile merge-stream. */
+
+static void
+print_merge_stream_usage_message (int error_p)
+{
+ FILE *file = error_p ? stderr : stdout;
+
+ fnotice (file, " merge-stream [options] [<file>] Merge coverage stream file (or stdin)\n"
+ " and coverage file contents\n");
+ fnotice (file, " -v, --verbose Verbose mode\n");
+ fnotice (file, " -w, --weight <w1,w2> Set weights (float point values)\n");
+}
+
+static const struct option merge_stream_options[] =
+{
+ { "verbose", no_argument, NULL, 'v' },
+ { "weight", required_argument, NULL, 'w' },
+ { 0, 0, 0, 0 }
+};
+
+/* Print merge-stream usage and exit. */
+
+static void ATTRIBUTE_NORETURN
+merge_stream_usage (void)
+{
+ fnotice (stderr, "Merge-stream subcomand usage:");
+ print_merge_stream_usage_message (true);
+ exit (FATAL_EXIT_CODE);
+}
+
+/* Driver for profile merge-stream sub-command. */
+
+static int
+do_merge_stream (int argc, char **argv)
+{
+ int opt;
+ int w1 = 1, w2 = 1;
+ struct gcov_info *merged_profile;
+
+ optind = 0;
+ while ((opt = getopt_long (argc, argv, "vw:",
+ merge_stream_options, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case 'v':
+ verbose = true;
+ gcov_set_verbose ();
+ break;
+ case 'w':
+ sscanf (optarg, "%d,%d", &w1, &w2);
+ if (w1 < 0 || w2 < 0)
+ fatal_error (input_location, "weights need to be non-negative");
+ break;
+ default:
+ merge_stream_usage ();
+ }
+ }
+
+ if (argc - optind > 1)
+ merge_stream_usage ();
+
+ merged_profile = gcov_profile_merge_stream (argv[optind], w1, w2);
+
+ if (merged_profile)
+ gcov_do_dump (merged_profile, 0, -1);
+ else if (verbose)
+ fnotice (stdout, "no profile files were merged\n");
+
+ return 0;
+}
+
/* If N_VAL is no-zero, normalize the profile by setting the largest counter
counter value to N_VAL and scale others counters proportionally.
Otherwise, multiply the all counters by SCALE. */
@@ -512,6 +578,7 @@ print_usage (int error_p)
fnotice (file, " -h, --help Print this help, then exit\n");
fnotice (file, " -v, --version Print version number, then exit\n");
print_merge_usage_message (error_p);
+ print_merge_stream_usage_message (error_p);
print_rewrite_usage_message (error_p);
print_overlap_usage_message (error_p);
fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
@@ -601,6 +668,8 @@ main (int argc, char **argv)
if (!strcmp (sub_command, "merge"))
return do_merge (argc - optind, argv + optind);
+ else if (!strcmp (sub_command, "merge-stream"))
+ return do_merge_stream (argc - optind, argv + optind);
else if (!strcmp (sub_command, "rewrite"))
return do_rewrite (argc - optind, argv + optind);
else if (!strcmp (sub_command, "overlap"))
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 863ee3d..7baec11 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -883,7 +883,7 @@ size_must_be_zero_p (tree size)
get_global_range_query ()->range_of_expr (vr, size);
if (vr.undefined_p ())
vr.set_varying (TREE_TYPE (size));
- vr.intersect (&valid_range);
+ vr.intersect (valid_range);
return vr.zero_p ();
}
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index 589b649..a0244e4 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -64,8 +64,10 @@ non_null_ref::adjust_range (irange &r, tree name, basic_block bb,
if (non_null_deref_p (name, bb, search_dom))
{
// Remove zero from the range.
- unsigned prec = TYPE_PRECISION (TREE_TYPE (name));
- r.intersect (wi::one (prec), wi::max_value (prec, UNSIGNED));
+ gcc_checking_assert (TYPE_UNSIGNED (TREE_TYPE (name)));
+ int_range<2> nz;
+ nz.set_nonzero (TREE_TYPE (name));
+ r.intersect (nz);
return true;
}
return false;
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index dfacf6f..3169e29 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -362,7 +362,7 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
tree max = vrp_val_max (ptrdiff_type_node);
unsigned prec = TYPE_PRECISION (TREE_TYPE (max));
wide_int wmaxm1 = wi::to_wide (max, prec) - 1;
- res.intersect (wi::zero (prec), wmaxm1);
+ res.intersect (int_range<2> (TREE_TYPE (max), wi::zero (prec), wmaxm1));
}
}
@@ -403,8 +403,8 @@ adjust_imagpart_expr (irange &res, const gimple *stmt)
tree cst = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (cst) == COMPLEX_CST)
{
- wide_int imag = wi::to_wide (TREE_IMAGPART (cst));
- res.intersect (imag, imag);
+ int_range<2> imag (TREE_IMAGPART (cst), TREE_IMAGPART (cst));
+ res.intersect (imag);
}
}
}
diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
index bed6dc2..fec6e87 100644
--- a/gcc/gimple-ssa-evrp-analyze.cc
+++ b/gcc/gimple-ssa-evrp-analyze.cc
@@ -110,9 +110,7 @@ evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range_equiv *vr)
if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
{
if (!vr->varying_p () && vr->constant_p ())
- set_range_info (lhs, vr->kind (),
- wi::to_wide (vr->min ()),
- wi::to_wide (vr->max ()));
+ set_range_info (lhs, *vr);
}
else if (POINTER_TYPE_P (TREE_TYPE (lhs))
&& range_includes_zero_p (vr) == 0)
@@ -209,7 +207,7 @@ evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
const value_range_equiv *old_vr
= get_value_range (vrs[i].first);
value_range tem (*old_vr);
- tem.intersect (vrs[i].second);
+ tem.legacy_verbose_intersect (vrs[i].second);
if (tem.equal_p (*old_vr))
{
free_value_range (vrs[i].second);
diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index c93f12f..9a84fff 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -4231,7 +4231,8 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
wide_int min = wi::shwi (retval[0], prec);
wide_int max = wi::shwi (retval[1], prec);
- set_range_info (lhs, VR_RANGE, min, max);
+ value_range r (TREE_TYPE (lhs), min, max);
+ set_range_info (lhs, r);
setrange = true;
}
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index dc3f0e9..11f4a32 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1018,7 +1018,7 @@ ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
return set_to_bottom ();
value_range save (m_vr);
- m_vr.union_ (other_vr);
+ m_vr.union_ (*other_vr);
return !m_vr.equal_p (save);
}
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index 0e59663..80e67e9 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -5987,11 +5987,13 @@ ipcp_update_vr (struct cgraph_node *node)
print_decs (vr[i].max, dump_file);
fprintf (dump_file, "]\n");
}
- set_range_info (ddef, vr[i].type,
- wide_int_storage::from (vr[i].min, prec,
- TYPE_SIGN (type)),
- wide_int_storage::from (vr[i].max, prec,
- TYPE_SIGN (type)));
+ value_range v (type,
+ wide_int_storage::from (vr[i].min, prec,
+ TYPE_SIGN (type)),
+ wide_int_storage::from (vr[i].max, prec,
+ TYPE_SIGN (type)),
+ vr[i].type);
+ set_range_info (ddef, v);
}
else if (POINTER_TYPE_P (TREE_TYPE (ddef))
&& vr[i].nonzero_p (TREE_TYPE (ddef)))
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 464a1f8..fa96250 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -63,24 +63,6 @@ min_limit (const_tree type)
return wi::min_value (TYPE_PRECISION (type) , TYPE_SIGN (type));
}
-// If the range of either op1 or op2 is undefined, set the result to
-// varying and return TRUE. If the caller truely cares about a result,
-// they should pass in a varying if it has an undefined that it wants
-// treated as a varying.
-
-inline bool
-empty_range_varying (irange &r, tree type,
- const irange &op1, const irange & op2)
-{
- if (op1.undefined_p () || op2.undefined_p ())
- {
- r.set_varying (type);
- return true;
- }
- else
- return false;
-}
-
// Return false if shifting by OP is undefined behavior. Otherwise, return
// true and the range it is to be shifted by. This allows trimming out of
// undefined ranges, leaving only valid ranges if there are any.
@@ -432,39 +414,10 @@ create_possibly_reversed_range (irange &r, tree type,
r.set (wide_int_to_tree (type, new_lb), wide_int_to_tree (type, new_ub));
}
-// Return an irange instance that is a boolean TRUE.
-
-static inline int_range<1>
-range_true (tree type)
-{
- unsigned prec = TYPE_PRECISION (type);
- return int_range<1> (type, wi::one (prec), wi::one (prec));
-}
-
-// Return an irange instance that is a boolean FALSE.
-
-static inline int_range<1>
-range_false (tree type)
-{
- unsigned prec = TYPE_PRECISION (type);
- return int_range<1> (type, wi::zero (prec), wi::zero (prec));
-}
-
-// Return an irange that covers both true and false.
-
-static inline int_range<1>
-range_true_and_false (tree type)
-{
- unsigned prec = TYPE_PRECISION (type);
- return int_range<1> (type, wi::zero (prec), wi::one (prec));
-}
-
-enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
-
// Return the summary information about boolean range LHS. If EMPTY/FULL,
// return the equivalent range for TYPE in R; if FALSE/TRUE, do nothing.
-static bool_range_state
+bool_range_state
get_bool_state (irange &r, const irange &lhs, tree val_type)
{
// If there is no result, then this is unexecutable.
@@ -488,37 +441,6 @@ get_bool_state (irange &r, const irange &lhs, tree val_type)
return BRS_TRUE;
}
-// For relation opcodes, first try to see if the supplied relation
-// forces a true or false result, and return that.
-// Then check for undefined operands. If none of this applies,
-// return false.
-
-static inline bool
-relop_early_resolve (irange &r, tree type, const irange &op1,
- const irange &op2, relation_kind rel,
- relation_kind my_rel)
-{
- // If known relation is a complete subset of this relation, always true.
- if (relation_union (rel, my_rel) == my_rel)
- {
- r = range_true (type);
- return true;
- }
-
- // If known relation has no subset of this relation, always false.
- if (relation_intersect (rel, my_rel) == VREL_EMPTY)
- {
- r = range_false (type);
- return true;
- }
-
- // If either operand is undefined, return VARYING.
- if (empty_range_varying (r, type, op1, op2))
- return true;
-
- return false;
-}
-
class operator_equal : public range_operator
{
@@ -541,7 +463,7 @@ public:
// Check if the LHS range indicates a relation between OP1 and OP2.
enum tree_code
-operator_equal::op1_op2_relation (const irange &lhs) const
+equal_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
return VREL_EMPTY;
@@ -556,6 +478,12 @@ operator_equal::op1_op2_relation (const irange &lhs) const
return VREL_NONE;
}
+enum tree_code
+operator_equal::op1_op2_relation (const irange &lhs) const
+{
+ return equal_op1_op2_relation (lhs);
+}
+
bool
operator_equal::fold_range (irange &r, tree type,
@@ -651,7 +579,7 @@ public:
// Check if the LHS range indicates a relation between OP1 and OP2.
enum tree_code
-operator_not_equal::op1_op2_relation (const irange &lhs) const
+not_equal_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
return VREL_EMPTY;
@@ -666,6 +594,12 @@ operator_not_equal::op1_op2_relation (const irange &lhs) const
return VREL_NONE;
}
+enum tree_code
+operator_not_equal::op1_op2_relation (const irange &lhs) const
+{
+ return not_equal_op1_op2_relation (lhs);
+}
+
bool
operator_not_equal::fold_range (irange &r, tree type,
const irange &op1,
@@ -821,7 +755,7 @@ public:
// Check if the LHS range indicates a relation between OP1 and OP2.
enum tree_code
-operator_lt::op1_op2_relation (const irange &lhs) const
+lt_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
return VREL_EMPTY;
@@ -836,6 +770,12 @@ operator_lt::op1_op2_relation (const irange &lhs) const
return VREL_NONE;
}
+enum tree_code
+operator_lt::op1_op2_relation (const irange &lhs) const
+{
+ return lt_op1_op2_relation (lhs);
+}
+
bool
operator_lt::fold_range (irange &r, tree type,
const irange &op1,
@@ -923,7 +863,7 @@ public:
// Check if the LHS range indicates a relation between OP1 and OP2.
enum tree_code
-operator_le::op1_op2_relation (const irange &lhs) const
+le_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
return VREL_EMPTY;
@@ -938,6 +878,12 @@ operator_le::op1_op2_relation (const irange &lhs) const
return VREL_NONE;
}
+enum tree_code
+operator_le::op1_op2_relation (const irange &lhs) const
+{
+ return le_op1_op2_relation (lhs);
+}
+
bool
operator_le::fold_range (irange &r, tree type,
const irange &op1,
@@ -1025,7 +971,7 @@ public:
// Check if the LHS range indicates a relation between OP1 and OP2.
enum tree_code
-operator_gt::op1_op2_relation (const irange &lhs) const
+gt_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
return VREL_EMPTY;
@@ -1040,6 +986,12 @@ operator_gt::op1_op2_relation (const irange &lhs) const
return VREL_NONE;
}
+enum tree_code
+operator_gt::op1_op2_relation (const irange &lhs) const
+{
+ return gt_op1_op2_relation (lhs);
+}
+
bool
operator_gt::fold_range (irange &r, tree type,
@@ -1126,7 +1078,7 @@ public:
// Check if the LHS range indicates a relation between OP1 and OP2.
enum tree_code
-operator_ge::op1_op2_relation (const irange &lhs) const
+ge_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
return VREL_EMPTY;
@@ -1141,6 +1093,12 @@ operator_ge::op1_op2_relation (const irange &lhs) const
return VREL_NONE;
}
+enum tree_code
+operator_ge::op1_op2_relation (const irange &lhs) const
+{
+ return ge_op1_op2_relation (lhs);
+}
+
bool
operator_ge::fold_range (irange &r, tree type,
const irange &op1,
@@ -3993,18 +3951,6 @@ pointer_or_operator::wi_fold (irange &r, tree type,
r.set_varying (type);
}
-// This implements the range operator tables as local objects in this file.
-
-class range_op_table
-{
-public:
- inline range_operator *operator[] (enum tree_code code);
-protected:
- void set (enum tree_code code, range_operator &op);
-private:
- range_operator *m_range_tree[MAX_TREE_CODES];
-};
-
// Return a pointer to the range_operator instance, if there is one
// associated with tree_code CODE.
diff --git a/gcc/range-op.h b/gcc/range-op.h
index a51969c..c93eb84 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -112,4 +112,76 @@ extern void wi_set_zero_nonzero_bits (tree type,
wide_int &maybe_nonzero,
wide_int &mustbe_nonzero);
+// op1_op2_relation methods that are the same across irange and frange.
+enum tree_code equal_op1_op2_relation (const irange &lhs);
+enum tree_code not_equal_op1_op2_relation (const irange &lhs);
+enum tree_code lt_op1_op2_relation (const irange &lhs);
+enum tree_code le_op1_op2_relation (const irange &lhs);
+enum tree_code gt_op1_op2_relation (const irange &lhs);
+enum tree_code ge_op1_op2_relation (const irange &lhs);
+
+enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
+bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type);
+
+// If the range of either op1 or op2 is undefined, set the result to
+// varying and return TRUE. If the caller truely cares about a result,
+// they should pass in a varying if it has an undefined that it wants
+// treated as a varying.
+
+inline bool
+empty_range_varying (irange &r, tree type,
+ const irange &op1, const irange & op2)
+{
+ if (op1.undefined_p () || op2.undefined_p ())
+ {
+ r.set_varying (type);
+ return true;
+ }
+ else
+ return false;
+}
+
+// For relation opcodes, first try to see if the supplied relation
+// forces a true or false result, and return that.
+// Then check for undefined operands. If none of this applies,
+// return false.
+
+inline bool
+relop_early_resolve (irange &r, tree type, const irange &op1,
+ const irange &op2, relation_kind rel,
+ relation_kind my_rel)
+{
+ // If known relation is a complete subset of this relation, always true.
+ if (relation_union (rel, my_rel) == my_rel)
+ {
+ r = range_true (type);
+ return true;
+ }
+
+ // If known relation has no subset of this relation, always false.
+ if (relation_intersect (rel, my_rel) == VREL_EMPTY)
+ {
+ r = range_false (type);
+ return true;
+ }
+
+ // If either operand is undefined, return VARYING.
+ if (empty_range_varying (r, type, op1, op2))
+ return true;
+
+ return false;
+}
+
+// This implements the range operator tables as local objects.
+
+class range_op_table
+{
+public:
+ range_operator *operator[] (enum tree_code code);
+protected:
+ void set (enum tree_code code, range_operator &op);
+private:
+ range_operator *m_range_tree[MAX_TREE_CODES];
+};
+
#endif // GCC_RANGE_OP_H
diff --git a/gcc/range.h b/gcc/range.h
index 5eb784b..5c70c66 100644
--- a/gcc/range.h
+++ b/gcc/range.h
@@ -25,4 +25,32 @@ value_range range_zero (tree type);
value_range range_nonzero (tree type);
value_range range_positives (tree type);
value_range range_negatives (tree type);
+
+// Return an irange instance that is a boolean TRUE.
+
+static inline int_range<1>
+range_true (tree type)
+{
+ unsigned prec = TYPE_PRECISION (type);
+ return int_range<1> (type, wi::one (prec), wi::one (prec));
+}
+
+// Return an irange instance that is a boolean FALSE.
+
+static inline int_range<1>
+range_false (tree type)
+{
+ unsigned prec = TYPE_PRECISION (type);
+ return int_range<1> (type, wi::zero (prec), wi::zero (prec));
+}
+
+// Return an irange that covers both true and false.
+
+static inline int_range<1>
+range_true_and_false (tree type)
+{
+ unsigned prec = TYPE_PRECISION (type);
+ return int_range<1> (type, wi::zero (prec), wi::one (prec));
+}
+
#endif // GCC_RANGE_H
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d3022f1..2a7aa6b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,90 @@
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcc.dg/gcov-info-to-gcda.c: Test __gcov_filename_to_gcfn().
+
+2022-04-28 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/105285
+ * gcc.dg/analyzer/symbolic-12.c: New test.
+
+2022-04-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/105425
+ * g++.dg/template/partial-specialization13.C: New test.
+
+2022-04-28 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.dg/lto/pr94157_0.c: Revert last change.
+ * lib/prune.exp (prune_gcc_output): Prune new linker warning.
+
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR lto/105399
+ * g++.dg/lto/pr105399_0.C: New test.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/104051
+ * g++.dg/coroutines/pr104051.C: New test.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/105301
+ * g++.dg/coroutines/pr105301.C: New test.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/105287
+ * g++.dg/coroutines/pr105287.C: New test.
+
+2022-04-28 Nathan Sidwell <nathan@acm.org>
+ Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/103868
+ * g++.dg/coroutines/pr103868.C: New test.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/memcpy-strategy-10.c: Account for
+ __USER_LABEL_PREFIX__.
+ * gcc.target/i386/memcpy-strategy-5.c: Likewise.
+ * gcc.target/i386/memset-strategy-5.c: Likewise.
+ * gcc.target/i386/memset-strategy-7.c: Likewise.
+
+2022-04-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++.target/i386/mv31.C: Add target supports guard for ifuncs.
+
+2022-04-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90107
+ * g++.dg/parse/qualified6.C: New test.
+
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/105331
+ * gcc.dg/pr105331.c: New test.
+
+2022-04-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/105219
+ * gcc.dg/vect/pr105219.c: New testcase.
+
+2022-04-28 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/105334
+ * gcc.target/powerpc/pr105334.c: New test.
+
+2022-04-28 Jia-Wei Chen <jiawei@iscas.ac.cn>
+
+ PR target/104676
+ * gcc.dg/torture/pr104676.c: Add "{target pthread}" check.
+
+2022-04-28 Xi Ruoyao <xry111@mengyan1223.wang>
+
+ * gcc.target/loongarch/zero-size-field-pass.c: New test.
+ * gcc.target/loongarch/zero-size-field-ret.c: New test.
+
2022-04-27 Thomas Koenig <tkoenig@gcc.gnu.org>
* gfortran.dg/pr70673.f90: Removed second invalid
diff --git a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
index b60ce84..6c83279 100644
--- a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
+++ b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
@@ -5,72 +5,72 @@ struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
bool nas2 = __has_nothrow_assign(C[]);
-bool nas3 = __has_nothrow_assign(I[]); // { dg-error "incomplete type" }
+bool nas3 = __has_nothrow_assign(I[]);
bool nas4 = __has_nothrow_assign(void);
bool nas5 = __has_nothrow_assign(const void);
bool tas1 = __has_trivial_assign(I); // { dg-error "incomplete type" }
bool tas2 = __has_trivial_assign(C[]);
-bool tas3 = __has_trivial_assign(I[]); // { dg-error "incomplete type" }
+bool tas3 = __has_trivial_assign(I[]);
bool tas4 = __has_trivial_assign(void);
bool tas5 = __has_trivial_assign(const void);
bool nco1 = __has_nothrow_constructor(I); // { dg-error "incomplete type" }
bool nco2 = __has_nothrow_constructor(C[]);
-bool nco3 = __has_nothrow_constructor(I[]); // { dg-error "incomplete type" }
+bool nco3 = __has_nothrow_constructor(I[]);
bool nco4 = __has_nothrow_constructor(void);
bool nco5 = __has_nothrow_constructor(const void);
bool tco1 = __has_trivial_constructor(I); // { dg-error "incomplete type" }
bool tco2 = __has_trivial_constructor(C[]);
-bool tco3 = __has_trivial_constructor(I[]); // { dg-error "incomplete type" }
+bool tco3 = __has_trivial_constructor(I[]);
bool tco4 = __has_trivial_constructor(void);
bool tco5 = __has_trivial_constructor(const void);
bool ncp1 = __has_nothrow_copy(I); // { dg-error "incomplete type" }
bool ncp2 = __has_nothrow_copy(C[]);
-bool ncp3 = __has_nothrow_copy(I[]); // { dg-error "incomplete type" }
+bool ncp3 = __has_nothrow_copy(I[]);
bool ncp4 = __has_nothrow_copy(void);
bool ncp5 = __has_nothrow_copy(const void);
bool tcp1 = __has_trivial_copy(I); // { dg-error "incomplete type" }
bool tcp2 = __has_trivial_copy(C[]);
-bool tcp3 = __has_trivial_copy(I[]); // { dg-error "incomplete type" }
+bool tcp3 = __has_trivial_copy(I[]);
bool tcp4 = __has_trivial_copy(void);
bool tcp5 = __has_trivial_copy(const void);
bool vde1 = __has_virtual_destructor(I); // { dg-error "incomplete type" }
bool vde2 = __has_virtual_destructor(C[]);
-bool vde3 = __has_virtual_destructor(I[]); // { dg-error "incomplete type" }
+bool vde3 = __has_virtual_destructor(I[]);
bool vde4 = __has_virtual_destructor(void);
bool vde5 = __has_virtual_destructor(const void);
bool tde1 = __has_trivial_destructor(I); // { dg-error "incomplete type" }
bool tde2 = __has_trivial_destructor(C[]);
-bool tde3 = __has_trivial_destructor(I[]); // { dg-error "incomplete type" }
+bool tde3 = __has_trivial_destructor(I[]);
bool tde4 = __has_trivial_destructor(void);
bool tde5 = __has_trivial_destructor(const void);
bool abs1 = __is_abstract(I); // { dg-error "incomplete type" }
bool abs2 = __is_abstract(C[]);
-bool abs3 = __is_abstract(I[]); // { dg-error "incomplete type" }
+bool abs3 = __is_abstract(I[]);
bool abs4 = __is_abstract(void);
bool abs5 = __is_abstract(const void);
bool pod1 = __is_pod(I); // { dg-error "incomplete type" }
bool pod2 = __is_pod(C[]);
-bool pod3 = __is_pod(I[]); // { dg-error "incomplete type" }
+bool pod3 = __is_pod(I[]);
bool pod4 = __is_pod(void);
bool pod5 = __is_pod(const void);
bool emp1 = __is_empty(I); // { dg-error "incomplete type" }
bool emp2 = __is_empty(C[]);
-bool emp3 = __is_empty(I[]); // { dg-error "incomplete type" }
+bool emp3 = __is_empty(I[]);
bool emp4 = __is_empty(void);
bool emp5 = __is_empty(const void);
bool pol1 = __is_polymorphic(I); // { dg-error "incomplete type" }
bool pol2 = __is_polymorphic(C[]);
-bool pol3 = __is_polymorphic(I[]); // { dg-error "incomplete type" }
+bool pol3 = __is_polymorphic(I[]);
bool pol4 = __is_polymorphic(void);
bool pol5 = __is_polymorphic(const void);
diff --git a/gcc/testsuite/g++.dg/lto/pr105399_0.C b/gcc/testsuite/g++.dg/lto/pr105399_0.C
new file mode 100644
index 0000000..fc9149a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr105399_0.C
@@ -0,0 +1,9 @@
+// PR lto/105399
+// { dg-lto-do link }
+// { dg-lto-options { { -fPIC -flto -Ofast } } }
+// { dg-require-effective-target shared }
+// { dg-require-effective-target fpic }
+// { dg-extra-ld-options "-shared -O2" }
+
+struct S { S (); };
+S::S () {}
diff --git a/gcc/testsuite/g++.dg/rtti/typeid-complete1.C b/gcc/testsuite/g++.dg/rtti/typeid-complete1.C
new file mode 100644
index 0000000..8d3fec4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/typeid-complete1.C
@@ -0,0 +1,14 @@
+// PR c++/102651
+
+#include <typeinfo>
+
+template <typename T>
+struct S : T{
+ T x;
+};
+
+const void *p;
+int main()
+{
+ p = &typeid( S<void>** );
+}
diff --git a/gcc/testsuite/g++.dg/template/partial-specialization13.C b/gcc/testsuite/g++.dg/template/partial-specialization13.C
new file mode 100644
index 0000000..b0903f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial-specialization13.C
@@ -0,0 +1,11 @@
+// PR c++/105425
+// { dg-do compile { target c++11 } }
+
+template<bool> struct when;
+template<class, class> struct A;
+template<class T, bool K> struct A<T, when<K>>; // #1
+template<class T> struct A<T, when<T(2) == 1>> {}; // #2
+A<int, when<true>> a1; // { dg-error "incomplete" }
+A<int, when<false>> a2;
+A<bool, when<true>> a3;
+A<bool, when<false>> a4; // { dg-error "incomplete" }
diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-31.C b/gcc/testsuite/g++.dg/warn/Wparentheses-31.C
new file mode 100644
index 0000000..f29234c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wparentheses-31.C
@@ -0,0 +1,59 @@
+/* Test that -Wparentheses warns for struct/class assignments,
+ except for explicit calls to operator= (). */
+/* PR c++/25689 */
+/* { dg-options "-Wparentheses" } */
+
+struct A
+{
+ A& operator= (int);
+ A operator= (double);
+ operator bool ();
+};
+
+struct B
+{
+ bool x;
+ B& operator= (int);
+ B operator= (double);
+ operator bool ();
+};
+
+struct C
+{
+ C& operator= (int);
+ virtual C operator= (double);
+ operator bool ();
+};
+
+/* Test empty class */
+void f1 (A a1, A a2)
+{
+ if (a1 = 0); /* { dg-warning "suggest parentheses" } */
+ if (a1 = 0.); /* { dg-warning "suggest parentheses" } */
+ if (a1.operator= (0));
+ if (a1.operator= (a2));
+
+ /* Ideally, we'd warn for empty classes using trivial operator= (below),
+ but we don't do so yet as it is a non-trivial COMPOUND_EXPR. */
+ if (a1 = a2); /* { dg-warning "suggest parentheses" "" { xfail *-*-* } } */
+}
+
+/* Test non-empty class */
+void f2 (B b1, B b2)
+{
+ if (b1 = 0); /* { dg-warning "suggest parentheses" } */
+ if (b1 = 0.); /* { dg-warning "suggest parentheses" } */
+ if (b1 = b2); /* { dg-warning "suggest parentheses" } */
+ if (b1.operator= (0));
+ if (b1.operator= (b2));
+}
+
+/* Test class with vtable */
+void f3 (C c1, C c2)
+{
+ if (c1 = 0); /* { dg-warning "suggest parentheses" } */
+ if (c1 = 0.); /* { dg-warning "suggest parentheses" } */
+ if (c1 = c2); /* { dg-warning "suggest parentheses" } */
+ if (c1.operator= (0));
+ if (c1.operator= (c2));
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-12.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-12.c
new file mode 100644
index 0000000..d7c50de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-12.c
@@ -0,0 +1,106 @@
+#include "analyzer-decls.h"
+
+void external_fn(void);
+
+struct st_1
+{
+ char *name;
+ unsigned size;
+};
+
+void test_1a (void *p, unsigned next_off)
+{
+ struct st_1 *r = p;
+
+ external_fn();
+
+ if (next_off >= r->size)
+ return;
+
+ if (next_off >= r->size)
+ /* We should have already returned if this is the case. */
+ __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
+
+void test_1b (void *p, unsigned next_off)
+{
+ struct st_1 *r = p;
+
+ if (next_off >= r->size)
+ return;
+
+ if (next_off >= r->size)
+ /* We should have already returned if this is the case. */
+ __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
+
+void test_1c (struct st_1 *r, unsigned next_off)
+{
+ if (next_off >= r->size)
+ return;
+
+ if (next_off >= r->size)
+ /* We should have already returned if this is the case. */
+ __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
+
+void test_1d (struct st_1 *r, unsigned next_off)
+{
+ external_fn();
+
+ if (next_off >= r->size)
+ return;
+
+ if (next_off >= r->size)
+ /* We should have already returned if this is the case. */
+ __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
+
+void test_1e (void *p, unsigned next_off)
+{
+ struct st_1 *r = p;
+
+ while (1)
+ {
+ external_fn();
+
+ if (next_off >= r->size)
+ return;
+
+ __analyzer_dump_path (); /* { dg-message "path" } */
+ }
+}
+
+struct st_2
+{
+ char *name;
+ unsigned arr[10];
+};
+
+void test_2a (void *p, unsigned next_off)
+{
+ struct st_2 *r = p;
+
+ external_fn();
+
+ if (next_off >= r->arr[5])
+ return;
+
+ if (next_off >= r->arr[5])
+ /* We should have already returned if this is the case. */
+ __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
+
+void test_2b (void *p, unsigned next_off, int idx)
+{
+ struct st_2 *r = p;
+
+ external_fn();
+
+ if (next_off >= r->arr[idx])
+ return;
+
+ if (next_off >= r->arr[idx])
+ /* We should have already returned if this is the case. */
+ __analyzer_dump_path (); /* { dg-bogus "path" } */
+}
diff --git a/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c b/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c
index 4583360..ca9b3e8 100644
--- a/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c
+++ b/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c
@@ -17,16 +17,20 @@ __gcov_info_to_gcda (const struct gcov_info *__info,
void *(*__allocate_fn) (unsigned, void *),
void *__arg);
+extern void
+__gcov_filename_to_gcfn (const char *__filename,
+ void (*__dump_fn) (const void *, unsigned, void *),
+ void *__arg);
+
extern const struct gcov_info *my_info;
static unsigned counter;
-static void
-filename (const char *f, void *arg)
-{
- assert (arg == &counter);
- assert (__builtin_strstr (f, "gcov-info-to-gcda.c") == 0);
-}
+static unsigned counter_after_filename;
+
+static int check_zero;
+
+static int check_after_filename;
static void
dump (const void *d, unsigned n, void *arg)
@@ -37,12 +41,28 @@ dump (const void *d, unsigned n, void *arg)
if (*m == 0)
{
const unsigned *u = d;
+ assert (*u == 0x6763666e);
+ check_zero = 1;
+ }
+ else if (*m == counter_after_filename)
+ {
+ const unsigned *u = d;
assert (*u == 0x67636461);
+ check_after_filename = 1;
}
*m += n;
}
+static void
+filename (const char *f, void *arg)
+{
+ assert (arg == &counter);
+ assert (__builtin_strstr (f, "gcov-info-to-gcda.c") == 0);
+ __gcov_filename_to_gcfn (f, dump, arg);
+ counter_after_filename = counter;
+}
+
static void *
allocate (unsigned length, void *arg)
{
@@ -54,6 +74,8 @@ int main()
{
__asm__ volatile (".set my_info, .LPBX2");
__gcov_info_to_gcda (my_info, filename, dump, allocate, &counter);
- assert (counter > 4);
+ assert (counter > 8);
+ assert (check_zero);
+ assert (check_after_filename);
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/lto/pr94157_0.c b/gcc/testsuite/gcc.dg/lto/pr94157_0.c
index a76141b..a6e308b 100644
--- a/gcc/testsuite/gcc.dg/lto/pr94157_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr94157_0.c
@@ -1,6 +1,6 @@
/* { dg-lto-do link } */
/* { dg-require-effective-target gas } */
-/* { dg-lto-options { { -O0 -fipa-vrp -flto -Wa,--noexecstack -Wa,--noexecstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wl,-z,execstack} } } */
+/* { dg-lto-options { { -O0 -fipa-vrp -flto -Wa,--noexecstack -Wa,--noexecstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack -Wa,--execstack } } } */
int main() {
diff --git a/gcc/testsuite/gcc.dg/pr105376.c b/gcc/testsuite/gcc.dg/pr105376.c
new file mode 100644
index 0000000..f19ecf4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr105376.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target dfp } } */
+/* { dg-options "-O -g" } */
+
+void
+foo (_Decimal64 d, _Decimal64 e)
+{
+ d -= -d;
+ d *= -e;
+}
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 4224985..04c6a1d 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -82,6 +82,11 @@ proc prune_gcc_output { text } {
regsub -all "(^|\n)\[^\n\]*file path prefix \[^\n\]* never used" $text "" text
regsub -all "(^|\n)\[^\n\]*linker input file unused since linking not done" $text "" text
+ # Ideally the tests would indicate that executable stacks were needed
+ # to the linker. But the option for that varies and may not even exist
+ # on some targets. So we're stuck pruning the warning.
+ regsub -all "(^|\n)(\[^\n\]*: warning:\[^\n\]*requires executable stack\[^\n\]*\n?)+" $text "\\1" text
+
# Ignore harmless warnings from Xcode 3.2.x.
regsub -all "(^|\n)\[^\n\]*ld: warning: can't add line info to anonymous symbol\[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*warning: DWARFDebugInfoEntry::AppendDependants\[^\n\]*AT_\[^\n\]*FORM_ref4\[^\n\]*" $text "" text
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index ca66a82..29bb758 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -253,8 +253,7 @@ remap_ssa_name (tree name, copy_body_data *id)
/* So can range-info. */
if (!POINTER_TYPE_P (TREE_TYPE (name))
&& SSA_NAME_RANGE_INFO (name))
- duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (name),
- SSA_NAME_RANGE_INFO (name));
+ duplicate_ssa_name_range_info (new_tree, name);
return new_tree;
}
@@ -291,8 +290,7 @@ remap_ssa_name (tree name, copy_body_data *id)
/* So can range-info. */
if (!POINTER_TYPE_P (TREE_TYPE (name))
&& SSA_NAME_RANGE_INFO (name))
- duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (name),
- SSA_NAME_RANGE_INFO (name));
+ duplicate_ssa_name_range_info (new_tree, name);
if (SSA_NAME_IS_DEFAULT_DEF (name))
{
/* By inlining function having uninitialized variable, we might
diff --git a/gcc/tree-ssa-copy.cc b/gcc/tree-ssa-copy.cc
index 7651352..7d636ec 100644
--- a/gcc/tree-ssa-copy.cc
+++ b/gcc/tree-ssa-copy.cc
@@ -556,9 +556,7 @@ fini_copy_prop (void)
&& SSA_NAME_RANGE_INFO (var)
&& !SSA_NAME_RANGE_INFO (copy_of[i].value)
&& var_bb == copy_of_bb)
- duplicate_ssa_name_range_info (copy_of[i].value,
- SSA_NAME_RANGE_TYPE (var),
- SSA_NAME_RANGE_INFO (var));
+ duplicate_ssa_name_range_info (copy_of[i].value, var);
}
}
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 21745bf..4a0cf2e 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -694,7 +694,7 @@ dom_jt_simplifier::simplify (gimple *stmt, gimple *within_stmt,
if (TREE_CODE (op) != SSA_NAME)
return NULL_TREE;
- const value_range_equiv *vr = m_vr_values->get_value_range (op);
+ const value_range *vr = m_vr_values->get_value_range (op);
return find_case_label_range (switch_stmt, vr);
}
if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index 7555793..2085597 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -1495,7 +1495,7 @@ powi_cost (HOST_WIDE_INT n)
static tree
powi_as_mults_1 (gimple_stmt_iterator *gsi, location_t loc, tree type,
- HOST_WIDE_INT n, tree *cache)
+ unsigned HOST_WIDE_INT n, tree *cache)
{
tree op0, op1, ssa_target;
unsigned HOST_WIDE_INT digit;
@@ -1548,7 +1548,7 @@ powi_as_mults (gimple_stmt_iterator *gsi, location_t loc,
memset (cache, 0, sizeof (cache));
cache[1] = arg0;
- result = powi_as_mults_1 (gsi, loc, type, (n < 0) ? -n : n, cache);
+ result = powi_as_mults_1 (gsi, loc, type, absu_hwi (n), cache);
if (n >= 0)
return result;
@@ -1572,11 +1572,9 @@ static tree
gimple_expand_builtin_powi (gimple_stmt_iterator *gsi, location_t loc,
tree arg0, HOST_WIDE_INT n)
{
- /* Avoid largest negative number. */
- if (n != -n
- && ((n >= -1 && n <= 2)
- || (optimize_function_for_speed_p (cfun)
- && powi_cost (n) <= POWI_MAX_MULTS)))
+ if ((n >= -1 && n <= 2)
+ || (optimize_function_for_speed_p (cfun)
+ && powi_cost (n) <= POWI_MAX_MULTS))
return powi_as_mults (gsi, loc, arg0, n);
return NULL_TREE;
@@ -4862,7 +4860,8 @@ optimize_spaceship (gimple *stmt)
wide_int wm1 = wi::minus_one (TYPE_PRECISION (integer_type_node));
wide_int w2 = wi::two (TYPE_PRECISION (integer_type_node));
- set_range_info (lhs, VR_RANGE, wm1, w2);
+ value_range vr (TREE_TYPE (lhs), wm1, w2);
+ set_range_info (lhs, vr);
}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 3eda825..8c9c46d 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -416,9 +416,7 @@ replace_phi_edge_with_variable (basic_block cond_block,
&& SSA_NAME_RANGE_INFO (phi_result)
&& gimple_bb (SSA_NAME_DEF_STMT (new_tree)) == cond_block
&& dbg_cnt (phiopt_edge_range))
- duplicate_ssa_name_range_info (new_tree,
- SSA_NAME_RANGE_TYPE (phi_result),
- SSA_NAME_RANGE_INFO (phi_result));
+ duplicate_ssa_name_range_info (new_tree, phi_result);
/* Change the PHI argument to new. */
SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree);
diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
index 47d70c8..a578ce6 100644
--- a/gcc/tree-ssa-pre.cc
+++ b/gcc/tree-ssa-pre.cc
@@ -3246,14 +3246,11 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
&& r.kind () == VR_RANGE
&& !wi::neg_p (r.lower_bound (), SIGNED)
&& !wi::neg_p (r.upper_bound (), SIGNED))
- /* Just handle extension and sign-changes of all-positive ranges. */
- set_range_info (temp, VR_RANGE,
- wide_int_storage::from (r.lower_bound (),
- TYPE_PRECISION (type),
- TYPE_SIGN (type)),
- wide_int_storage::from (r.upper_bound (),
- TYPE_PRECISION (type),
- TYPE_SIGN (type)));
+ {
+ /* Just handle extension and sign-changes of all-positive ranges. */
+ range_cast (r, type);
+ set_range_info (temp, r);
+ }
}
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index d4d0aba..3c90c1e 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -6304,9 +6304,7 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
&& SSA_NAME_RANGE_INFO (lhs)
&& ! SSA_NAME_RANGE_INFO (sprime)
&& b == sprime_b)
- duplicate_ssa_name_range_info (sprime,
- SSA_NAME_RANGE_TYPE (lhs),
- SSA_NAME_RANGE_INFO (lhs));
+ duplicate_ssa_name_range_info (sprime, lhs);
}
/* Inhibit the use of an inserted PHI on a loop header when
diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index 9ae25d1..1e5f911 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -1951,7 +1951,8 @@ set_strlen_range (tree lhs, wide_int min, wide_int max,
if (min == max)
return wide_int_to_tree (size_type_node, min);
- set_range_info (lhs, VR_RANGE, min, max);
+ value_range vr (TREE_TYPE (lhs), min, max);
+ set_range_info (lhs, vr);
return lhs;
}
@@ -4343,8 +4344,9 @@ strlen_pass::handle_builtin_string_cmp ()
known to be unequal set the range of the result to non-zero.
This allows the call to be eliminated if its result is only
used in tests for equality to zero. */
- wide_int zero = wi::zero (TYPE_PRECISION (TREE_TYPE (lhs)));
- set_range_info (lhs, VR_ANTI_RANGE, zero, zero);
+ value_range nz;
+ nz.set_nonzero (TREE_TYPE (lhs));
+ set_range_info (lhs, nz);
return false;
}
/* When the two strings are definitely equal (such as when they
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index e0a6884..c957597 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -389,7 +389,7 @@ set_range_info_raw (tree name, enum value_range_kind range_type,
/* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name
NAME while making sure we don't store useless range info. */
-void
+static void
set_range_info (tree name, enum value_range_kind range_type,
const wide_int_ref &min, const wide_int_ref &max)
{
@@ -720,7 +720,7 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
/* Creates a duplicate of the range_info_def at RANGE_INFO of type
RANGE_TYPE for use by the SSA name NAME. */
-void
+static void
duplicate_ssa_name_range_info (tree name, enum value_range_kind range_type,
struct range_info_def *range_info)
{
@@ -743,6 +743,14 @@ duplicate_ssa_name_range_info (tree name, enum value_range_kind range_type,
SSA_NAME_RANGE_INFO (name) = new_range_info;
}
+void
+duplicate_ssa_name_range_info (tree name, tree src)
+{
+ gcc_checking_assert (!POINTER_TYPE_P (TREE_TYPE (src)));
+ duplicate_ssa_name_range_info (name,
+ SSA_NAME_RANGE_TYPE (src),
+ SSA_NAME_RANGE_INFO (src));
+}
/* Creates a duplicate of a ssa name NAME tobe defined by statement STMT
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 7538ba9..8c419b1 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -67,8 +67,6 @@ struct GTY ((variable_size)) range_info_def {
if (VAR)
/* Sets the value range to SSA. */
-extern void set_range_info (tree, enum value_range_kind, const wide_int_ref &,
- const wide_int_ref &);
extern void set_range_info (tree, const value_range &);
extern void set_nonzero_bits (tree, const wide_int_ref &);
extern wide_int get_nonzero_bits (const_tree);
@@ -92,8 +90,7 @@ extern void set_ptr_nonnull (tree);
extern tree copy_ssa_name_fn (struct function *, tree, gimple *);
extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *);
extern tree duplicate_ssa_name_fn (struct function *, tree, gimple *);
-extern void duplicate_ssa_name_range_info (tree, enum value_range_kind,
- struct range_info_def *);
+extern void duplicate_ssa_name_range_info (tree dest, tree src);
extern void reset_flow_sensitive_info (tree);
extern void reset_flow_sensitive_info_in_bb (basic_block);
extern void release_defs (gimple *);
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index e4381eb..3eddda6 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -2056,22 +2056,28 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters,
if (stmts != NULL && log_vf)
{
if (niters_no_overflow)
- set_range_info (niters_vector, VR_RANGE,
- wi::one (TYPE_PRECISION (type)),
- wi::rshift (wi::max_value (TYPE_PRECISION (type),
- TYPE_SIGN (type)),
- exact_log2 (const_vf),
- TYPE_SIGN (type)));
+ {
+ value_range vr (type,
+ wi::one (TYPE_PRECISION (type)),
+ wi::rshift (wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type)),
+ exact_log2 (const_vf),
+ TYPE_SIGN (type)));
+ set_range_info (niters_vector, vr);
+ }
/* For VF == 1 the vector IV might also overflow so we cannot
assert a minimum value of 1. */
else if (const_vf > 1)
- set_range_info (niters_vector, VR_RANGE,
- wi::one (TYPE_PRECISION (type)),
- wi::rshift (wi::max_value (TYPE_PRECISION (type),
- TYPE_SIGN (type))
- - (const_vf - 1),
- exact_log2 (const_vf), TYPE_SIGN (type))
- + 1);
+ {
+ value_range vr (type,
+ wi::one (TYPE_PRECISION (type)),
+ wi::rshift (wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type))
+ - (const_vf - 1),
+ exact_log2 (const_vf), TYPE_SIGN (type))
+ + 1);
+ set_range_info (niters_vector, vr);
+ }
}
}
*niters_vector_ptr = niters_vector;
@@ -2888,9 +2894,12 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
/* It's guaranteed that vector loop bound before vectorization is at
least VF, so set range information for newly generated var. */
if (new_var_p)
- set_range_info (niters, VR_RANGE,
- wi::to_wide (build_int_cst (type, vf)),
- wi::to_wide (TYPE_MAX_VALUE (type)));
+ {
+ value_range vr (type,
+ wi::to_wide (build_int_cst (type, vf)),
+ wi::to_wide (TYPE_MAX_VALUE (type)));
+ set_range_info (niters, vr);
+ }
/* Prolog iterates at most bound_prolog times, latch iterates at
most bound_prolog - 1 times. */
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index f53a634..ab7dade 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -6634,19 +6634,14 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
need it to get at the number of vector stmts which wasn't
yet initialized for the instance root. */
}
- if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)
- stmt_info = vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (stmt_info));
- else
+ if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
{
- gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info)
- == vect_double_reduction_def);
use_operand_p use_p;
gimple *use_stmt;
bool res = single_imm_use (gimple_phi_result (stmt_info->stmt),
&use_p, &use_stmt);
gcc_assert (res);
phi_info = loop_vinfo->lookup_stmt (use_stmt);
- stmt_info = vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (phi_info));
}
/* PHIs should not participate in patterns. */
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index e9f19d0..0cbd9d3 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -768,7 +768,7 @@ extract_range_from_plus_minus_expr (value_range *vr,
value_range vrres;
extract_range_from_plus_minus_expr (&vrres, code, expr_type,
&vrtem1, vr1_);
- vr->union_ (&vrres);
+ vr->union_ (vrres);
}
return;
}
@@ -782,7 +782,7 @@ extract_range_from_plus_minus_expr (value_range *vr,
value_range vrres;
extract_range_from_plus_minus_expr (&vrres, code, expr_type,
vr0_, &vrtem1);
- vr->union_ (&vrres);
+ vr->union_ (vrres);
}
return;
}
@@ -2470,7 +2470,7 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op)
int_range_max label_range (CASE_LOW (label), case_high);
if (!types_compatible_p (label_range.type (), range_of_op->type ()))
range_cast (label_range, range_of_op->type ());
- label_range.intersect (range_of_op);
+ label_range.intersect (*range_of_op);
if (label_range == *range_of_op)
return label;
}
@@ -2494,7 +2494,7 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op)
int_range_max label_range (CASE_LOW (min_label), case_high);
if (!types_compatible_p (label_range.type (), range_of_op->type ()))
range_cast (label_range, range_of_op->type ());
- label_range.intersect (range_of_op);
+ label_range.intersect (*range_of_op);
if (label_range.undefined_p ())
return gimple_switch_label (switch_stmt, 0);
}
@@ -3742,9 +3742,16 @@ vrp_asserts::remove_range_assertions ()
&& all_imm_uses_in_stmt_or_feed_cond (var, stmt,
single_pred (bb)))
{
- set_range_info (var, SSA_NAME_RANGE_TYPE (lhs),
- SSA_NAME_RANGE_INFO (lhs)->get_min (),
- SSA_NAME_RANGE_INFO (lhs)->get_max ());
+ /* We could use duplicate_ssa_name_range_info here
+ instead of peeking inside SSA_NAME_RANGE_INFO,
+ but the aforementioned asserts that the
+ destination has no global range. This is
+ slated for removal anyhow. */
+ value_range r (TREE_TYPE (lhs),
+ SSA_NAME_RANGE_INFO (lhs)->get_min (),
+ SSA_NAME_RANGE_INFO (lhs)->get_max (),
+ SSA_NAME_RANGE_TYPE (lhs));
+ set_range_info (var, r);
maybe_set_nonzero_bits (single_pred_edge (bb), var);
}
}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 3c39be4..4cf3785 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "escaped_string.h"
#include "gimple-range.h"
#include "gomp-constants.h"
+#include "dfp.h"
/* Tree code classes. */
@@ -2383,6 +2384,26 @@ build_real (tree type, REAL_VALUE_TYPE d)
REAL_VALUE_TYPE *dp;
int overflow = 0;
+ /* dconst{1,2,m1,half} are used in various places in
+ the middle-end and optimizers, allow them here
+ even for decimal floating point types as an exception
+ by converting them to decimal. */
+ if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))
+ && d.cl == rvc_normal
+ && !d.decimal)
+ {
+ if (memcmp (&d, &dconst1, sizeof (d)) == 0)
+ decimal_real_from_string (&d, "1");
+ else if (memcmp (&d, &dconst2, sizeof (d)) == 0)
+ decimal_real_from_string (&d, "2");
+ else if (memcmp (&d, &dconstm1, sizeof (d)) == 0)
+ decimal_real_from_string (&d, "-1");
+ else if (memcmp (&d, &dconsthalf, sizeof (d)) == 0)
+ decimal_real_from_string (&d, "0.5");
+ else
+ gcc_unreachable ();
+ }
+
/* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
Consider doing it via real_convert now. */
diff --git a/gcc/value-range-equiv.cc b/gcc/value-range-equiv.cc
index 731fa53..77c6f5c 100644
--- a/gcc/value-range-equiv.cc
+++ b/gcc/value-range-equiv.cc
@@ -188,7 +188,7 @@ value_range_equiv::equiv_add (const_tree var,
}
void
-value_range_equiv::intersect (const value_range_equiv *other)
+value_range_equiv::legacy_verbose_intersect (const value_range_equiv *other)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -238,7 +238,7 @@ value_range_equiv::intersect (const value_range_equiv *other)
}
void
-value_range_equiv::union_ (const value_range_equiv *other)
+value_range_equiv::legacy_verbose_union_ (const value_range_equiv *other)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h
index 11b806c..0aa1069 100644
--- a/gcc/value-range-equiv.h
+++ b/gcc/value-range-equiv.h
@@ -48,8 +48,8 @@ class GTY((user)) value_range_equiv : public value_range
bool operator== (const value_range_equiv &) const /* = delete */;
bool operator!= (const value_range_equiv &) const /* = delete */;
- void intersect (const value_range_equiv *);
- void union_ (const value_range_equiv *);
+ void legacy_verbose_intersect (const value_range_equiv *);
+ void legacy_verbose_union_ (const value_range_equiv *);
bool equal_p (const value_range_equiv &, bool ignore_equivs) const;
/* Types of value ranges. */
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 000bbcf..94301b3 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1442,7 +1442,7 @@ irange::legacy_union (irange *vr0, const irange *vr1)
may not be the smallest possible such range. */
void
-irange::union_ (const irange *other)
+irange::legacy_verbose_union_ (const irange *other)
{
if (legacy_mode_p ())
{
@@ -1482,7 +1482,7 @@ irange::union_ (const irange *other)
}
void
-irange::intersect (const irange *other)
+irange::legacy_verbose_intersect (const irange *other)
{
if (legacy_mode_p ())
{
diff --git a/gcc/value-range.h b/gcc/value-range.h
index d4cba22..90a395f 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -73,7 +73,6 @@ public:
// In-place operators.
void union_ (const irange &);
void intersect (const irange &);
- void intersect (const wide_int& lb, const wide_int& ub);
void invert ();
// Operator overloads.
@@ -97,8 +96,8 @@ public:
bool may_contain_p (tree) const; // DEPRECATED
void set (tree); // DEPRECATED
bool equal_p (const irange &) const; // DEPRECATED
- void union_ (const class irange *); // DEPRECATED
- void intersect (const irange *); // DEPRECATED
+ void legacy_verbose_union_ (const class irange *); // DEPRECATED
+ void legacy_verbose_intersect (const irange *); // DEPRECATED
protected:
irange (tree *, unsigned);
@@ -135,6 +134,7 @@ private:
void irange_set_1bit_anti_range (tree, tree);
bool varying_compatible_p () const;
+ void intersect (const wide_int& lb, const wide_int& ub);
unsigned char m_num_ranges;
unsigned char m_max_ranges;
ENUM_BITFIELD(value_range_kind) m_kind : 8;
@@ -397,9 +397,8 @@ inline
irange::irange (tree *base, unsigned nranges)
{
m_base = base;
- m_num_ranges = 0;
m_max_ranges = nranges;
- m_kind = VR_UNDEFINED;
+ set_undefined ();
}
// Constructors for int_range<>.
@@ -550,7 +549,7 @@ irange::union_ (const irange &r)
{
dump_flags_t m_flags = dump_flags;
dump_flags &= ~TDF_DETAILS;
- irange::union_ (&r);
+ irange::legacy_verbose_union_ (&r);
dump_flags = m_flags;
}
@@ -559,7 +558,7 @@ irange::intersect (const irange &r)
{
dump_flags_t m_flags = dump_flags;
dump_flags &= ~TDF_DETAILS;
- irange::intersect (&r);
+ irange::legacy_verbose_intersect (&r);
dump_flags = m_flags;
}
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index f94da313..301996d 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -266,7 +266,7 @@ vr_values::update_value_range (const_tree var, value_range_equiv *new_vr)
value_range_equiv nr;
get_global_range_query ()->range_of_expr (nr, const_cast <tree> (var));
if (!nr.undefined_p ())
- new_vr->intersect (&nr);
+ new_vr->legacy_verbose_intersect (&nr);
}
/* Update the value range, if necessary. If we cannot allocate a lattice
@@ -750,7 +750,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
gcc_unreachable ();
/* Finally intersect the new range with what we already know about var. */
- vr_p->intersect (get_value_range (var));
+ vr_p->legacy_verbose_intersect (get_value_range (var));
}
/* Extract value range information from an ASSERT_EXPR EXPR and store
@@ -1014,7 +1014,7 @@ vr_values::extract_range_from_cond_expr (value_range_equiv *vr, gassign *stmt)
/* The resulting value range is the union of the operand ranges */
vr->deep_copy (vr0);
- vr->union_ (vr1);
+ vr->legacy_verbose_union_ (vr1);
}
@@ -2300,10 +2300,10 @@ simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops
for previously LE_ or LT_EXPR and GT_EXPR otherwise, but
the comments next to the enclosing if suggest it's not
generally profitable to do so. */
- vro.intersect (vr0);
+ vro.legacy_verbose_intersect (vr0);
if (vro.undefined_p ())
return boolean_false_node;
- vri.intersect (vr0);
+ vri.legacy_verbose_intersect (vr0);
if (vri.undefined_p ())
return boolean_true_node;
}
@@ -2803,7 +2803,7 @@ vr_values::extract_range_from_phi_node (gphi *phi,
if (first)
vr_result->deep_copy (vr_arg);
else
- vr_result->union_ (vr_arg);
+ vr_result->legacy_verbose_union_ (vr_arg);
first = false;
if (vr_result->varying_p ())
@@ -2980,9 +2980,12 @@ simplify_using_ranges::simplify_truth_ops_using_ranges
gsi_insert_before (gsi, newop, GSI_SAME_STMT);
if (INTEGRAL_TYPE_P (TREE_TYPE (tem))
&& TYPE_PRECISION (TREE_TYPE (tem)) > 1)
- set_range_info (tem, VR_RANGE,
- wi::zero (TYPE_PRECISION (TREE_TYPE (tem))),
- wi::one (TYPE_PRECISION (TREE_TYPE (tem))));
+ {
+ value_range vr (TREE_TYPE (tem),
+ wi::zero (TYPE_PRECISION (TREE_TYPE (tem))),
+ wi::one (TYPE_PRECISION (TREE_TYPE (tem))));
+ set_range_info (tem, vr);
+ }
gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem);
}
/* Or without. */
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index ce0cb32..f597666 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,68 @@
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (ftw_read_file): Improve notice using xstrerror().
+ (gcov_profile_merge_stream): Likewise.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (consume_stream): New.
+ (get_target_profiles_for_merge): Likewise.
+ (gcov_profile_merge_stream): Likewise.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (ftw_read_file): Use size_t for strlen() variables.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (read_gcda_file): Do not open file.
+ (ftw_read_file): Open file here.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (read_gcda_file): Prepend new info object to global
+ list.
+ (ftw_read_file): Remove list append here.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (read_gcda_file): Do not duplicate filename.
+ (ftw_read_file): Duplicate filename for read_gcda_file().
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcov.h (__gcov_info_to_gcda): Mention __gcov_filename_to_gcfn().
+ (__gcov_filename_to_gcfn): Declare and document.
+ * libgcov-driver.c (dump_string): New.
+ (__gcov_filename_to_gcfn): Likewise.
+ (__gcov_info_to_gcda): Adjust comment to match C11 standard language.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov.h (gcov_seek): Remove define and declaration.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-driver-system.c (gcov_exit_open_gcda_file): Add mode
+ parameter. Pass mode to gcov_open() calls.
+ * libgcov-driver.c (dump_one_gcov): Add mode parameter. Pass mode to
+ gcov_exit_open_gcda_file() call.
+ (gcov_do_dump): Add mode parameter. Pass mode to dump_one_gcov()
+ calls.
+ (__gcov_dump_one): Open file for reading and writing.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-driver-system.c (gcov_exit_open_gcda_file): Open file for
+ reading and writing.
+ * libgcov-util.c (read_gcda_file): Open file for reading.
+ * libgcov.h (gcov_open): Delete declaration.
+
+2022-04-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libgcov-util.c (gcov_profile_merge): Return the list of merged
+ profiles. Accept empty target and source profile lists.
+
2022-04-08 Sergei Trofimovich <siarheit@google.com>
* config/ia64/fde-glibc.c: Make a no-op in inhibit_libc mode.
diff --git a/libgcc/gcov.h b/libgcc/gcov.h
index cea9302..cdd4206 100644
--- a/libgcc/gcov.h
+++ b/libgcc/gcov.h
@@ -43,7 +43,8 @@ extern void __gcov_dump (void);
stream. The ALLOCATE_FN callback shall allocate memory with a size in
characters specified by the first callback parameter. The ARG parameter is
a user-provided argument passed as the last argument to the callback
- functions. */
+ functions. It is recommended to use the __gcov_filename_to_gcfn()
+ in the filename callback function. */
extern void
__gcov_info_to_gcda (const struct gcov_info *__info,
@@ -52,4 +53,18 @@ __gcov_info_to_gcda (const struct gcov_info *__info,
void *(*__allocate_fn) (unsigned, void *),
void *__arg);
+/* Convert the FILENAME to a gcfn data stream. The DUMP_FN callback is
+ subsequently called with chunks (the begin and length of the chunk are
+ passed as the first two callback parameters) of the gcfn data stream.
+ The ARG parameter is a user-provided argument passed as the last
+ argument to the DUMP_FN callback function. This function is intended
+ to be used by the filename callback of __gcov_info_to_gcda(). The gcfn
+ data stream is used by the merge-stream subcommand of the gcov-tool to
+ get the filename associated with a gcda data stream. */
+
+extern void
+__gcov_filename_to_gcfn (const char *__filename,
+ void (*__dump_fn) (const void *, unsigned, void *),
+ void *__arg);
+
#endif /* GCC_GCOV_H */
diff --git a/libgcc/libgcov-driver-system.c b/libgcc/libgcov-driver-system.c
index eef6e3c..ac405c3 100644
--- a/libgcc/libgcov-driver-system.c
+++ b/libgcc/libgcov-driver-system.c
@@ -261,7 +261,8 @@ allocate_filename_struct (struct gcov_filename *gf)
static int
gcov_exit_open_gcda_file (struct gcov_info *gi_ptr,
- struct gcov_filename *gf)
+ struct gcov_filename *gf,
+ int mode)
{
int append_slash = 0;
const char *fname = gi_ptr->filename;
@@ -309,7 +310,7 @@ gcov_exit_open_gcda_file (struct gcov_info *gi_ptr,
gf->filename = replace_filename_variables (gf->filename);
- if (!gcov_open (gf->filename))
+ if (!gcov_open (gf->filename, mode))
{
/* Open failed likely due to missed directory.
Create directory and retry to open file. */
@@ -318,7 +319,7 @@ gcov_exit_open_gcda_file (struct gcov_info *gi_ptr,
fprintf (stderr, "profiling:%s:Skip\n", gf->filename);
return -1;
}
- if (!gcov_open (gf->filename))
+ if (!gcov_open (gf->filename, mode))
{
fprintf (stderr, "profiling:%s:Cannot open\n", gf->filename);
return -1;
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index 7e52c56..d4517d2 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -410,6 +410,23 @@ dump_counter (gcov_type counter,
dump_unsigned (0, dump_fn, arg);
}
+/* Dump the STRING using the DUMP handler called with ARG. */
+
+static inline void
+dump_string (const char *string,
+ void (*dump_fn) (const void *, unsigned, void *),
+ void *arg)
+{
+ unsigned length = 0;
+
+ if (string)
+ length = strlen (string) + 1;
+
+ dump_unsigned (length, dump_fn, arg);
+ if (string)
+ (*dump_fn) (string, length, arg);
+}
+
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
/* Store all TOP N counters where each has a dynamic length. */
@@ -595,14 +612,14 @@ write_one_data (const struct gcov_info *gi_ptr,
static void
dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
unsigned run_counted ATTRIBUTE_UNUSED,
- gcov_type run_max ATTRIBUTE_UNUSED)
+ gcov_type run_max ATTRIBUTE_UNUSED, int mode)
{
struct gcov_summary summary = {};
int error;
gcov_unsigned_t tag;
fn_buffer = 0;
- error = gcov_exit_open_gcda_file (gi_ptr, gf);
+ error = gcov_exit_open_gcda_file (gi_ptr, gf, mode);
if (error == -1)
return;
@@ -649,13 +666,13 @@ read_fatal:;
/* Dump all the coverage counts for the program. It first computes program
summary and then traverses gcov_list list and dumps the gcov_info
- objects one by one. */
+ objects one by one. Use MODE to open files. */
#if !IN_GCOV_TOOL
static
#endif
void
-gcov_do_dump (struct gcov_info *list, int run_counted)
+gcov_do_dump (struct gcov_info *list, int run_counted, int mode)
{
struct gcov_info *gi_ptr;
struct gcov_filename gf;
@@ -678,7 +695,7 @@ gcov_do_dump (struct gcov_info *list, int run_counted)
/* Now merge each file. */
for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
{
- dump_one_gcov (gi_ptr, &gf, run_counted, run_max);
+ dump_one_gcov (gi_ptr, &gf, run_counted, run_max, mode);
free (gf.filename);
}
@@ -701,7 +718,7 @@ __gcov_dump_one (struct gcov_root *root)
if (root->dumped)
return;
- gcov_do_dump (root->list, root->run_counted);
+ gcov_do_dump (root->list, root->run_counted, 0);
root->dumped = 1;
root->run_counted = 1;
@@ -768,7 +785,7 @@ __gcov_init (struct gcov_info *info)
#ifdef NEED_L_GCOV_INFO_TO_GCDA
/* Convert the gcov info to a gcda data stream. It is intended for
- free-standing environments which do not support the C library file I/O. */
+ freestanding environments which do not support the C library file I/O. */
void
__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
@@ -780,4 +797,17 @@ __gcov_info_to_gcda (const struct gcov_info *gi_ptr,
(*filename_fn) (gi_ptr->filename, arg);
write_one_data (gi_ptr, NULL, dump_fn, allocate_fn, arg);
}
+
+/* Convert the filename to a gcfn data stream. It is intended for
+ freestanding environments which do not support the C library file I/O. */
+
+void
+__gcov_filename_to_gcfn (const char *filename,
+ void (*dump_fn) (const void *, unsigned, void *),
+ void *arg)
+{
+ dump_unsigned (GCOV_FILENAME_MAGIC, dump_fn, arg);
+ dump_unsigned (GCOV_VERSION, dump_fn, arg);
+ dump_string (filename, dump_fn, arg);
+}
#endif /* NEED_L_GCOV_INFO_TO_GCDA */
diff --git a/libgcc/libgcov-util.c b/libgcc/libgcov-util.c
index ba7fb92..ba4670b 100644
--- a/libgcc/libgcov-util.c
+++ b/libgcc/libgcov-util.c
@@ -268,17 +268,10 @@ read_gcda_file (const char *filename)
k_ctrs_mask[i] = 0;
k_ctrs_types = 0;
- if (!gcov_open (filename))
- {
- fnotice (stderr, "%s:cannot open\n", filename);
- return NULL;
- }
-
/* Read magic. */
if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
{
fnotice (stderr, "%s:not a gcov data file\n", filename);
- gcov_close ();
return NULL;
}
@@ -287,7 +280,6 @@ read_gcda_file (const char *filename)
if (version != GCOV_VERSION)
{
fnotice (stderr, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION);
- gcov_close ();
return NULL;
}
@@ -296,16 +288,14 @@ read_gcda_file (const char *filename)
sizeof (struct gcov_ctr_info) * GCOV_COUNTERS, 1);
obj_info->version = version;
+ obj_info->filename = filename;
obstack_init (&fn_info);
num_fn_info = 0;
curr_fn_info = 0;
- {
- size_t len = strlen (filename) + 1;
- char *str_dup = (char*) xmalloc (len);
- memcpy (str_dup, filename, len);
- obj_info->filename = str_dup;
- }
+ /* Prepend to global gcov info list. */
+ obj_info->next = gcov_info_head;
+ gcov_info_head = obj_info;
/* Read stamp. */
obj_info->stamp = gcov_read_unsigned ();
@@ -381,7 +371,6 @@ read_gcda_file (const char *filename)
}
read_gcda_finalize (obj_info);
- gcov_close ();
return obj_info;
}
@@ -395,9 +384,8 @@ ftw_read_file (const char *filename,
const struct stat *status ATTRIBUTE_UNUSED,
int type)
{
- int filename_len;
- int suffix_len;
- struct gcov_info *obj_info;
+ size_t filename_len;
+ size_t suffix_len;
/* Only read regular files. */
if (type != FTW_F)
@@ -415,12 +403,14 @@ ftw_read_file (const char *filename,
if (verbose)
fnotice (stderr, "reading file: %s\n", filename);
- obj_info = read_gcda_file (filename);
- if (!obj_info)
- return 0;
+ if (!gcov_open (filename, 1))
+ {
+ fnotice (stderr, "%s:cannot open:%s\n", filename, xstrerror (errno));
+ return 0;
+ }
- obj_info->next = gcov_info_head;
- gcov_info_head = obj_info;
+ (void)read_gcda_file (xstrdup (filename));
+ gcov_close ();
return 0;
}
@@ -674,16 +664,16 @@ find_match_gcov_info (struct gcov_info **array, int size,
}
/* Merge the list of gcov_info objects from SRC_PROFILE to TGT_PROFILE.
- Return 0 on success: without mismatch.
- Reutrn 1 on error. */
+ Return the list of merged gcov_info objects. Return NULL if the list is
+ empty. */
-int
+struct gcov_info *
gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile,
int w1, int w2)
{
struct gcov_info *gi_ptr;
struct gcov_info **tgt_infos;
- struct gcov_info *tgt_tail;
+ struct gcov_info **tgt_tail;
struct gcov_info **in_src_not_tgt;
unsigned tgt_cnt = 0, src_cnt = 0;
unsigned unmatch_info_cnt = 0;
@@ -703,7 +693,10 @@ gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile
for (gi_ptr = tgt_profile, i = 0; gi_ptr; gi_ptr = gi_ptr->next, i++)
tgt_infos[i] = gi_ptr;
- tgt_tail = tgt_infos[tgt_cnt - 1];
+ if (tgt_cnt)
+ tgt_tail = &tgt_infos[tgt_cnt - 1]->next;
+ else
+ tgt_tail = &tgt_profile;
/* First pass on tgt_profile, we multiply w1 to all counters. */
if (w1 > 1)
@@ -732,14 +725,109 @@ gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile
gi_ptr = in_src_not_tgt[i];
gcov_merge (gi_ptr, gi_ptr, w2 - 1);
gi_ptr->next = NULL;
- tgt_tail->next = gi_ptr;
- tgt_tail = gi_ptr;
+ *tgt_tail = gi_ptr;
+ tgt_tail = &gi_ptr->next;
}
free (in_src_not_tgt);
free (tgt_infos);
- return 0;
+ return tgt_profile;
+}
+
+/* Deserialize gcov_info objects and associated filenames from the file
+ specified by FILENAME to create a profile list. When FILENAME is NULL, read
+ from stdin. Return the profile list. */
+
+struct gcov_info *
+deserialize_profiles (const char *filename)
+{
+ read_profile_dir_init ();
+
+ while (true)
+ {
+ unsigned version;
+ const char *filename_of_info;
+ struct gcov_info *obj_info;
+
+ if (!gcov_magic (gcov_read_unsigned (), GCOV_FILENAME_MAGIC))
+ {
+ if (gcov_is_error () != 2)
+ fnotice (stderr, "%s:not a gcfn stream\n", filename);
+ break;
+ }
+
+ version = gcov_read_unsigned ();
+ if (version != GCOV_VERSION)
+ {
+ fnotice (stderr, "%s:incorrect gcov version %d vs %d \n",
+ filename, version, GCOV_VERSION);
+ break;
+ }
+
+ filename_of_info = gcov_read_string ();
+ if (!filename_of_info)
+ {
+ fnotice (stderr, "%s:no filename in gcfn stream\n",
+ filename);
+ break;
+ }
+
+ obj_info = read_gcda_file (filename);
+ if (!obj_info)
+ break;
+
+ obj_info->filename = filename_of_info;
+ }
+
+ return gcov_info_head;
+}
+
+/* For each profile of the list specified by SRC_PROFILE, read the GCDA file of
+ the profile. If a GCDA file exists, add the profile to a list. Return the
+ profile list. */
+
+struct gcov_info *
+get_target_profiles_for_merge (struct gcov_info *src_profile)
+{
+ struct gcov_info *gi_ptr;
+
+ read_profile_dir_init ();
+
+ for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
+ if (gcov_open (gi_ptr->filename, 1))
+ {
+ (void)read_gcda_file (gi_ptr->filename);
+ gcov_close ();
+ }
+
+ return gcov_info_head;
+}
+
+/* Deserialize gcov_info objects and associated filenames from the file
+ specified by FILENAME to create a source profile list. When FILENAME is
+ NULL, read from stdin. Use the filenames of the source profile list to get
+ a target profile list. Merge the source profile list into the target
+ profile list using weights W1 and W2. Return the list of merged gcov_info
+ objects. Return NULL if the list is empty. */
+
+struct gcov_info *
+gcov_profile_merge_stream (const char *filename, int w1, int w2)
+{
+ struct gcov_info *tgt_profile;
+ struct gcov_info *src_profile;
+
+ if (!gcov_open (filename, 1))
+ {
+ fnotice (stderr, "%s:cannot open:%s\n", filename, xstrerror (errno));
+ return NULL;
+ }
+
+ src_profile = deserialize_profiles (filename ? filename : "<stdin>");
+ gcov_close ();
+ tgt_profile = get_target_profiles_for_merge (src_profile);
+
+ return gcov_profile_merge (tgt_profile, src_profile, w1, w2);
}
typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 40e845c..487bd14 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -115,7 +115,6 @@ typedef unsigned gcov_type_unsigned __attribute__ ((mode (QI)));
#define gcov_open __gcov_open
#define gcov_close __gcov_close
#define gcov_position __gcov_position
-#define gcov_seek __gcov_seek
#define gcov_rewrite __gcov_rewrite
#define gcov_is_error __gcov_is_error
#define gcov_write_unsigned __gcov_write_unsigned
@@ -343,11 +342,9 @@ extern int __gcov_execve (const char *, char *const [], char *const [])
ATTRIBUTE_HIDDEN;
/* Functions that only available in libgcov. */
-GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/,
const struct gcov_summary *)
ATTRIBUTE_HIDDEN;
-GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE void gcov_rewrite (void) ATTRIBUTE_HIDDEN;
/* "Counts" stored in gcda files can be a real counter value, or
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 1b36447..aff1ab9 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,10 @@
+2022-04-28 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/104717
+ * testsuite/libgomp.oacc-fortran/print-1.f90: Add OpenACC
+ privatization scanning. For GCN offloading compilation, raise
+ '-mgang-private-size'.
+
2022-04-26 Jakub Jelinek <jakub@redhat.com>
PR libgomp/105358
diff --git a/libphobos/ChangeLog b/libphobos/ChangeLog
index 0a9d916..de5cce4 100644
--- a/libphobos/ChangeLog
+++ b/libphobos/ChangeLog
@@ -1,3 +1,7 @@
+2022-04-28 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/MERGE: Merge upstream druntime e361d200.
+
2022-04-26 Iain Buclaw <ibuclaw@gdcproject.org>
* libdruntime/gcc/emutls.d (emutlsDestroyThread): Clear the per-thread
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 461cc8a..c174262 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,19 @@
+2022-04-28 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/99290
+ * src/c++17/fs_ops.cc (fs::copy): Pass error_code to
+ directory_iterator constructor, and check on each iteration.
+ * src/filesystem/ops.cc (fs::copy): Likewise.
+ * testsuite/27_io/filesystem/operations/copy.cc: Check for
+ errors during recursion.
+ * testsuite/experimental/filesystem/operations/copy.cc:
+ Likewise.
+
+2022-04-28 François Dumont <fdumont@gcc.gnu.org>
+
+ * config/abi/pre/gnu-versioned-namespace.ver: Remove
+ std::random_device::* pattern.
+
2022-04-27 Jakub Jelinek <jakub@redhat.com>
* config/abi/post/x86_64-linux-gnu/baseline_symbols.txt: Update.
diff --git a/maintainer-scripts/ChangeLog b/maintainer-scripts/ChangeLog
index 8f30655..d9d586d 100644
--- a/maintainer-scripts/ChangeLog
+++ b/maintainer-scripts/ChangeLog
@@ -1,3 +1,8 @@
+2022-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ * crontab: Snapshots from trunk are now GCC 13 related.
+ Add GCC 12 snapshots from the respective branch.
+
2021-05-14 Jakub Jelinek <jakub@redhat.com>
* crontab: Stop doing gcc-8 snapshots.
diff --git a/maintainer-scripts/crontab b/maintainer-scripts/crontab
index 93612a3..a3417c3 100644
--- a/maintainer-scripts/crontab
+++ b/maintainer-scripts/crontab
@@ -1,7 +1,8 @@
16 0 * * * sh /home/gccadmin/scripts/update_version_git
50 0 * * * sh /home/gccadmin/scripts/update_web_docs_git
55 0 * * * sh /home/gccadmin/scripts/update_web_docs_libstdcxx_git
-32 22 * * 4 sh /home/gccadmin/scripts/gcc_release -s 9:releases/gcc-9 -l -d /sourceware/snapshot-tmp/gcc all
-32 22 * * 5 sh /home/gccadmin/scripts/gcc_release -s 10:releases/gcc-10 -l -d /sourceware/snapshot-tmp/gcc all
-32 22 * * 6 sh /home/gccadmin/scripts/gcc_release -s 11:releases/gcc-11 -l -d /sourceware/snapshot-tmp/gcc all
-32 22 * * 7 sh /home/gccadmin/scripts/gcc_release -s 12:master -l -d /sourceware/snapshot-tmp/gcc all
+32 22 * * 3 sh /home/gccadmin/scripts/gcc_release -s 9:releases/gcc-9 -l -d /sourceware/snapshot-tmp/gcc all
+32 22 * * 4 sh /home/gccadmin/scripts/gcc_release -s 10:releases/gcc-10 -l -d /sourceware/snapshot-tmp/gcc all
+32 22 * * 5 sh /home/gccadmin/scripts/gcc_release -s 11:releases/gcc-11 -l -d /sourceware/snapshot-tmp/gcc all
+32 22 * * 6 sh /home/gccadmin/scripts/gcc_release -s 12:releases/gcc-12 -l -d /sourceware/snapshot-tmp/gcc all
+32 22 * * 7 sh /home/gccadmin/scripts/gcc_release -s 13:master -l -d /sourceware/snapshot-tmp/gcc all