This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Strenghten assumption about function start and end line (PR gcov-profile/88045).
- From: Martin Liška <mliska at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 16 Nov 2018 14:48:29 +0100
- Subject: [PATCH] Strenghten assumption about function start and end line (PR gcov-profile/88045).
Hi.
As mentioned in the PR, we should guarantee that a function ends before
it starts (from source line perspective).
For gcc-8 branch, a work-around would be needed.
Survives tests and bootstrap on x86_64-linux-gnu.
Ready for trunk and gcc-8 branch?
Thanks,
Martin
gcc/ChangeLog:
2018-11-16 Martin Liska <mliska@suse.cz>
PR gcov/88045
* coverage.c (coverage_begin_function): Add assert.
gcc/testsuite/ChangeLog:
2018-11-16 Martin Liska <mliska@suse.cz>
PR gcov/88045
* g++.dg/gcov/pr88045.C: New test.
---
gcc/coverage.c | 4 +-
gcc/testsuite/g++.dg/gcov/pr88045.C | 90 +++++++++++++++++++++++++++++
2 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/gcov/pr88045.C
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 599a3bb9aeb..f0cbc1e46ef 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -639,7 +639,9 @@ coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
expanded_location endloc = expand_location (cfun->function_end_locus);
/* Function can start in a single file and end in another one. */
- gcov_write_unsigned (endloc.file == xloc.file ? endloc.line : xloc.line);
+ int end_line = endloc.file == xloc.file ? endloc.line : xloc.line;
+ gcc_assert (xloc.line <= end_line);
+ gcov_write_unsigned (end_line);
gcov_write_length (offset);
return !gcov_is_error ();
diff --git a/gcc/testsuite/g++.dg/gcov/pr88045.C b/gcc/testsuite/g++.dg/gcov/pr88045.C
new file mode 100644
index 00000000000..1b077a5e61a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/pr88045.C
@@ -0,0 +1,90 @@
+// PR gcov-profile/88045
+// { dg-options "-fprofile-arcs -ftest-coverage -std=c++11" }
+// { dg-do run { target native } }
+
+#include <numeric>
+#include <vector>
+#include <stdlib.h>
+
+struct Foo {
+ size_t size() const { return n; };
+ const size_t n;
+ explicit Foo(size_t a_n) : n{a_n} {};
+};
+
+template<template<typename...> class C, typename Head, typename... Tail>
+struct make_with_tail {
+ using type = C<Tail...>;
+};
+
+template<template<typename...> class C, typename T, typename Head, typename... Tail>
+struct make_with_tail_1 {
+using type = C<T, Tail...>;
+};
+
+template<typename Head, typename... Tail>
+struct head {
+ using type = Head;
+};
+template<typename... Ts>
+struct Tree {
+ using root_type = typename head<Ts...>::type;
+ using branch_type = typename make_with_tail<Tree, Ts...>::type;
+ Tree(root_type a_root, std::vector<branch_type> a_branches) :
+ root{std::move(a_root)},
+ branches{std::move(a_branches)}
+ {
+ }
+
+ explicit Tree(root_type a_root) : root{std::move(a_root)}, branches{root.size()}
+ {
+ }
+
+ root_type root;
+ std::vector<branch_type> branches;
+};
+
+template<>
+struct Tree<> {
+};
+
+template<typename... Axes>
+size_t size(const Tree<Axes...>& tree)
+{
+ return std::accumulate(
+ tree.branches.begin(),
+ tree.branches.end(),
+ 0,
+ [](const size_t& count, const typename make_with_tail<Tree, Axes...>::type& branch) {
+ return count + size(branch);
+ });
+}
+
+template<>
+inline size_t size(const Tree<>& /* empty tree */)
+{
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ size(Tree<Foo, Foo, Foo>{Foo{4}, {Tree<Foo, Foo>{Foo{2}, {Tree<Foo>{Foo{205}},
+ Tree<Foo>{Foo{261}}}},
+ Tree<Foo, Foo>{Foo{4}, {Tree<Foo>{Foo{875}},
+ Tree<Foo>{Foo{492}},
+ Tree<Foo>{Foo{398}},
+ Tree<Foo>{Foo{302}}}},
+ Tree<Foo, Foo>{Foo{6}, {Tree<Foo>{Foo{111}},
+ Tree<Foo>{Foo{436}},
+ Tree<Foo>{Foo{388}},
+ Tree<Foo>{Foo{879}},
+ Tree<Foo>{Foo{783}},
+ Tree<Foo>{Foo{735}}}},
+ Tree<Foo, Foo>{Foo{3}, {Tree<Foo>{Foo{791}},
+ Tree<Foo>{Foo{ 5}},
+ Tree<Foo>{Foo{841}}}}}});
+
+ return 0;
+}
+
+// { dg-final { run-gcov pr88045.C } }
>From cf3cf8a56ff576501701b2d830867a350e205b24 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 16 Nov 2018 13:59:09 +0100
Subject: [PATCH] Make a workaround for PR gcov-profile/88045.
gcc/ChangeLog:
2018-11-16 Martin Liska <mliska@suse.cz>
PR gcov-profile/88045
* coverage.c (coverage_begin_function): One can't relly on the
fact that function ends on the same line it starts or later.
gcc/testsuite/ChangeLog:
2018-11-16 Martin Liska <mliska@suse.cz>
PR gcov-profile/88045
* g++.dg/gcov/pr88045.C: New test.
---
gcc/coverage.c | 6 +-
gcc/testsuite/g++.dg/gcov/pr88045.C | 90 +++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/gcov/pr88045.C
diff --git a/gcc/coverage.c b/gcc/coverage.c
index bae3d507638..75628b1748f 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -672,7 +672,11 @@ coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
expanded_location endloc = expand_location (cfun->function_end_locus);
/* Function can start in a single file and end in another one. */
- gcov_write_unsigned (endloc.file == xloc.file ? endloc.line : xloc.line);
+ /* Work-around for PR gcov-profile/88045. */
+ int end_line = endloc.file == xloc.file ? endloc.line : xloc.line;
+ if (xloc.line > end_line)
+ end_line = xloc.line;
+ gcov_write_unsigned (end_line);
gcov_write_length (offset);
return !gcov_is_error ();
diff --git a/gcc/testsuite/g++.dg/gcov/pr88045.C b/gcc/testsuite/g++.dg/gcov/pr88045.C
new file mode 100644
index 00000000000..1b077a5e61a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/pr88045.C
@@ -0,0 +1,90 @@
+// PR gcov-profile/88045
+// { dg-options "-fprofile-arcs -ftest-coverage -std=c++11" }
+// { dg-do run { target native } }
+
+#include <numeric>
+#include <vector>
+#include <stdlib.h>
+
+struct Foo {
+ size_t size() const { return n; };
+ const size_t n;
+ explicit Foo(size_t a_n) : n{a_n} {};
+};
+
+template<template<typename...> class C, typename Head, typename... Tail>
+struct make_with_tail {
+ using type = C<Tail...>;
+};
+
+template<template<typename...> class C, typename T, typename Head, typename... Tail>
+struct make_with_tail_1 {
+using type = C<T, Tail...>;
+};
+
+template<typename Head, typename... Tail>
+struct head {
+ using type = Head;
+};
+template<typename... Ts>
+struct Tree {
+ using root_type = typename head<Ts...>::type;
+ using branch_type = typename make_with_tail<Tree, Ts...>::type;
+ Tree(root_type a_root, std::vector<branch_type> a_branches) :
+ root{std::move(a_root)},
+ branches{std::move(a_branches)}
+ {
+ }
+
+ explicit Tree(root_type a_root) : root{std::move(a_root)}, branches{root.size()}
+ {
+ }
+
+ root_type root;
+ std::vector<branch_type> branches;
+};
+
+template<>
+struct Tree<> {
+};
+
+template<typename... Axes>
+size_t size(const Tree<Axes...>& tree)
+{
+ return std::accumulate(
+ tree.branches.begin(),
+ tree.branches.end(),
+ 0,
+ [](const size_t& count, const typename make_with_tail<Tree, Axes...>::type& branch) {
+ return count + size(branch);
+ });
+}
+
+template<>
+inline size_t size(const Tree<>& /* empty tree */)
+{
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ size(Tree<Foo, Foo, Foo>{Foo{4}, {Tree<Foo, Foo>{Foo{2}, {Tree<Foo>{Foo{205}},
+ Tree<Foo>{Foo{261}}}},
+ Tree<Foo, Foo>{Foo{4}, {Tree<Foo>{Foo{875}},
+ Tree<Foo>{Foo{492}},
+ Tree<Foo>{Foo{398}},
+ Tree<Foo>{Foo{302}}}},
+ Tree<Foo, Foo>{Foo{6}, {Tree<Foo>{Foo{111}},
+ Tree<Foo>{Foo{436}},
+ Tree<Foo>{Foo{388}},
+ Tree<Foo>{Foo{879}},
+ Tree<Foo>{Foo{783}},
+ Tree<Foo>{Foo{735}}}},
+ Tree<Foo, Foo>{Foo{3}, {Tree<Foo>{Foo{791}},
+ Tree<Foo>{Foo{ 5}},
+ Tree<Foo>{Foo{841}}}}}});
+
+ return 0;
+}
+
+// { dg-final { run-gcov pr88045.C } }
--
2.19.1