Search code examples
c++unit-testingcode-coveragegcovlcov

constexpr constructor won't show coverage data


Today I was rewriting my matrix class to be constexpr. I have(had) 100% unit test coverage on this class but I noticed after I converted almost all functions to constexpr a part of the constructor is marked in the lcov as no longer covered at all.

Here is the class with just the constructor.

template<typename T, std::size_t m, std::size_t n>
class Matrix
{
static_assert(std::is_arithmetic<T>::value,
                  "Matrix can only be declared with a type where "
                  "std::is_arithmetic is true.");

public:
    constexpr Matrix(
        std::initializer_list<std::initializer_list<T>> matrix_data)
    {
        if (matrix_data.size() != m)
        {
            throw std::invalid_argument("Invalid amount of rows.");
        }

        for (const auto& col : matrix_data)
        {
            if (col.size() != n)
            {
                throw std::invalid_argument("Invalid amount of columns.");
            }
        }


        std::size_t pos_i = 0;
        std::size_t pos_j = 0;

        for (auto i = matrix_data.begin(); i != matrix_data.end(); ++i)
        {
            for (auto j = i->begin(); j != i->end(); ++j)
            {
                this->data[pos_i][pos_j] = *j;
                ++pos_j;
            }
            ++pos_i;
            pos_j = 0;
        }
    }


private:
    std::array<std::array<T, n>, m> data{};

};


int main()
{
    Matrix<double, 2, 2> mat = {
        {1, 2},
        {3, 4}
    };

    return 0;
}

I am using gcc 7.2 with lcov 1.13


Solution

  • I have(had) 100% unit test coverage on this class but I noticed after I converted almost all functions to constexpr a part of the constructor is marked in the lcov as no longer covered at all.

    lcov's indication of non covered code means that gcov didn't instrument it.

    Anything marked constexpr is evaluated at compile time, gcov coverage data is gathered at runtime.

    So that's one reason I'd suspect, why you don't get coverage data for any constexpr function.


    As you have templated code, I'm not sure if I'm up to date, but I experienced that gcov doesn't instrument templates very well, and you might be left with zero coverage data for them.

    Similar reasoning as with what I said above for constexpr, templates are evaluated/instantiated at compile time. It would be at least hard to instrument all actually used template instantiations in a reasonable way.