https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88045

            Bug ID: 88045
           Summary: Call to std::accumulate causes gcov to crash
           Product: gcc
           Version: 8.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: gcov-profile
          Assignee: unassigned at gcc dot gnu.org
          Reporter: loximann at gmail dot com
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

Created attachment 45012
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45012&action=edit
Minimum reproducible example

gcov 8.2.1 segfaults for a certain file.

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
zsh: abort (core dumped)  gcov main.gcda

The stack trace looks like this:

#0  0x00007ffff7c9153f in raise () from /lib64/libc.so.6
#1  0x00007ffff7c7b895 in abort () from /lib64/libc.so.6
#2  0x0000000000438f27 in __gnu_cxx::__verbose_terminate_handler() [clone
.cold.1] ()
#3  0x000000000046833c in __cxxabiv1::__terminate(void (*)()) ()
#4  0x0000000000468397 in std::terminate() ()
#5  0x00000000004692b8 in __cxa_throw ()
#6  0x00000000004675b4 in operator new(unsigned long) ()
#7  0x0000000000454fa4 in std::vector<line_info, std::allocator<line_info>
>::_M_default_append(unsigned long) ()
#8  0x000000000043b542 in main ()

The minimal reproducible example I managed to produce:

###################################################################
#include <numeric>
#include <vector>

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;
}
###################################################################

Replacing the call to std::accumulate with a loop fixes the issue.

Reply via email to