从断言调用时缺少 llvm-cov 覆盖
llvm-cov coverage missing when called from assertion
我有以下头文件:
power.hpp:
#pragma once
#include <type_traits>
template <typename T, typename R = decltype(std::declval<T>() * std::declval<T>())>
constexpr inline R square(const T& x_) noexcept;
power.inl:
#pragma once
#include "power.hpp"
template <typename T, typename R>
constexpr inline R square(const T& x_) noexcept
{
return (x_ * x_);
}
power_unit_test.cpp:
#include <power.inl>
int main()
{
static_assert(square(2) == 4);
assert(square(2) == 4);
square(2);
return (0);
}
在使用 clang++ 中使用标志 -fprofile-instr-generate
和 -fcoverage-mapping
进行编译后。 运行 单元测试二进制文件,我得到一份报告,告诉我 main 中的三行中的每一行都被调用了,但是函数内容只被使用了一次。此用法来自对 square(2)
的独立调用,断言似乎无法正确生成覆盖率报告。
如果我删除独立的 square(2)
那么覆盖率不会达到 100%,因为断言由于某种原因没有产生覆盖率。
覆盖率报告如下:
power.inl:
22| | template <typename T, typename R>
23| | constexpr inline R square(const T& x_) noexcept
24| 0| {
25| 0| return (x_ * x_);
26| 0| }
power_unit_test.cpp
29| |int main()
30| 1|{
31| 1| static_assert(arc::math::sq(2) == 4);
32| 1| assert(arc::math::sq(2) == 4);
33| 1| // arc::math::sq(2);
34| 1|
35| 1| return (0);
36| 1|}
请您帮我理解为什么没有像我期望的那样报告报道?这是 llvm-cov 中的错误还是我不理解覆盖意图?
在 MacOS 上使用自制程序的 clang 7.0.1 进行编译。使用 CMake 3.13.2 作为构建系统。
您遇到的问题是您的编译器正在为两种断言方法内联 square()
函数。由于代码是内联的,它永远不会调用您的外部代码。
您的第一个想法可能是删除 inline
标识符,但这行不通。这是因为您的编译器很可能足够聪明,可以识别 square()
函数 可以 内联并继续执行。最终结果是外部代码没有被调用。
所以你需要一种方法来绕过 square()
函数的内联。您可以使用函数指针来执行此操作。请参阅对 main
函数的以下修改:
int main()
{
int (*f_ptr)(const int&); // Ptr to func that takes 'const int&' and returns 'int'
f_ptr = □
static_assert(square(2) == 4); // Cant use 'f_ptr' here
assert(f_ptr(2) == 4);
f_ptr(2);
return (0);
}
在上面的代码中,我们将对 square(const int&)
的显式调用替换为指向函数 f_ptr
的指针。因此,编译器不会自动内联断言中的函数,代码将被成功调用两次。结果:
power.cpp:
4| |template <typename T, typename R>
5| |constexpr inline R square(const T& x_) noexcept
6| 2|{
7| 2| return (x_ * x_);
8| 2|}
power_unit_test.cpp:
5| |int main()
6| 1|{
7| 1| int (*f_ptr)(const int&);
8| 1| f_ptr = □
9| 1|
10| 1| static_assert(square(2) == 4);
11| 1| assert(f_ptr(2) == 4);
12| 1| f_ptr(2);
13| 1|
14| 1| return (0);
15| 1|}
快速说明。由于 static_assert
本质上是一个编译时断言,我们不能用我们的函数指针替换对 square()
的调用,因为函数指针不是 constant expressions。但别担心,如果您尝试在此处用函数指针 f_ptr(2)
替换 square(2)
,您的编译器会很聪明地发出警告。
我有以下头文件:
power.hpp:
#pragma once
#include <type_traits>
template <typename T, typename R = decltype(std::declval<T>() * std::declval<T>())>
constexpr inline R square(const T& x_) noexcept;
power.inl:
#pragma once
#include "power.hpp"
template <typename T, typename R>
constexpr inline R square(const T& x_) noexcept
{
return (x_ * x_);
}
power_unit_test.cpp:
#include <power.inl>
int main()
{
static_assert(square(2) == 4);
assert(square(2) == 4);
square(2);
return (0);
}
在使用 clang++ 中使用标志 -fprofile-instr-generate
和 -fcoverage-mapping
进行编译后。 运行 单元测试二进制文件,我得到一份报告,告诉我 main 中的三行中的每一行都被调用了,但是函数内容只被使用了一次。此用法来自对 square(2)
的独立调用,断言似乎无法正确生成覆盖率报告。
如果我删除独立的 square(2)
那么覆盖率不会达到 100%,因为断言由于某种原因没有产生覆盖率。
覆盖率报告如下:
power.inl:
22| | template <typename T, typename R>
23| | constexpr inline R square(const T& x_) noexcept
24| 0| {
25| 0| return (x_ * x_);
26| 0| }
power_unit_test.cpp
29| |int main()
30| 1|{
31| 1| static_assert(arc::math::sq(2) == 4);
32| 1| assert(arc::math::sq(2) == 4);
33| 1| // arc::math::sq(2);
34| 1|
35| 1| return (0);
36| 1|}
请您帮我理解为什么没有像我期望的那样报告报道?这是 llvm-cov 中的错误还是我不理解覆盖意图?
在 MacOS 上使用自制程序的 clang 7.0.1 进行编译。使用 CMake 3.13.2 作为构建系统。
您遇到的问题是您的编译器正在为两种断言方法内联 square()
函数。由于代码是内联的,它永远不会调用您的外部代码。
您的第一个想法可能是删除 inline
标识符,但这行不通。这是因为您的编译器很可能足够聪明,可以识别 square()
函数 可以 内联并继续执行。最终结果是外部代码没有被调用。
所以你需要一种方法来绕过 square()
函数的内联。您可以使用函数指针来执行此操作。请参阅对 main
函数的以下修改:
int main()
{
int (*f_ptr)(const int&); // Ptr to func that takes 'const int&' and returns 'int'
f_ptr = □
static_assert(square(2) == 4); // Cant use 'f_ptr' here
assert(f_ptr(2) == 4);
f_ptr(2);
return (0);
}
在上面的代码中,我们将对 square(const int&)
的显式调用替换为指向函数 f_ptr
的指针。因此,编译器不会自动内联断言中的函数,代码将被成功调用两次。结果:
power.cpp:
4| |template <typename T, typename R>
5| |constexpr inline R square(const T& x_) noexcept
6| 2|{
7| 2| return (x_ * x_);
8| 2|}
power_unit_test.cpp:
5| |int main()
6| 1|{
7| 1| int (*f_ptr)(const int&);
8| 1| f_ptr = □
9| 1|
10| 1| static_assert(square(2) == 4);
11| 1| assert(f_ptr(2) == 4);
12| 1| f_ptr(2);
13| 1|
14| 1| return (0);
15| 1|}
快速说明。由于 static_assert
本质上是一个编译时断言,我们不能用我们的函数指针替换对 square()
的调用,因为函数指针不是 constant expressions。但别担心,如果您尝试在此处用函数指针 f_ptr(2)
替换 square(2)
,您的编译器会很聪明地发出警告。