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 <mli...@suse.cz> PR gcov/88045 * coverage.c (coverage_begin_function): Add assert. gcc/testsuite/ChangeLog: 2018-11-16 Martin Liska <mli...@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 <mli...@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 <mli...@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 <mli...@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