c++ - LLVM 覆盖被 if-constexpr 混淆
问题描述
在以下位置使用常量表达式时,我遇到了一个关于 LLVM 覆盖率的奇怪问题if-statement
:
template<typename T>
int foo(const T &val)
{
int idx = 0;
if constexpr(std::is_trivially_copyable<T>::value && sizeof(T) <= sizeof(int)
{
memcpy(&idx, &v, sizeof(T));
}
else
{
//store val and assign its index to idx
}
return idx;
}
执行的实例化:
int idx1 = foo<int>(10);
int idx2 = foo<long long>(10);
int idx3 = foo<std::string>(std::string("Hello"));
int idx4 = foo<std::vector<int>>(std::vector<int>{1,2,3,4,5});
在这些中没有一个是sizeof(T) <= sizeof(int)
执行的。然而,在第一种情况下,实例化 ( int
) 的主体if
确实按应有的方式执行。在其他情况下,它显示为已执行。
编译命令行的相关部分:
/usr/bin/clang++ -g -O0 -Wall -Wextra -fprofile-instr-generate -fcoverage-mapping -target x86_64-pc-linux-gnu -pipe -fexceptions -fvisibility=default -fPIC -DQT_CORE_LIB -DQT_TESTLIB_LIB -I(...) -std=c++17 -o test.o -c test.cpp
链接器命令行的相关部分:
/usr/bin/clang++ -Wl,-m,elf_x86_64,-rpath,/home/michael/Qt/5.11.2/gcc_64/lib -L/home/michael/Qt/5.11.2/gcc_64/lib -fprofile-instr-generate -fcoverage-mapping -target x86_64-pc-linux-gnu -o testd test.o -lpthread -fuse-ld=lld
当条件被提取到它自己的函数时,两个int
实例long long
在覆盖范围中正确显示为执行sizeof(T) <= sizeof(int)
部分。什么可能导致这种行为以及如何解决它?它是 Clang/LLVM cov 中的错误吗?
有任何想法吗?
编辑:这似乎是 LLVM 中的一个已知错误(虽然尚不清楚 LLVM-cov 还是 Clang):
https://bugs.llvm.org/show_bug.cgi?id=36086
https://bugs.chromium.org/p/chromium/issues/detail?id=845575
解决方案
首先,sizeof(T) <= sizeof(int)
应该在代码的编译时执行,所以很有可能,编译没有针对覆盖进行分析。
接下来,这三种类型中只有long long
looks trivially_copyable
,但它的大小(很可能)大于 of int
,所以then-clause 不会为它们执行,甚至不会编译。由于一切都发生在模板函数中,因此未编译未执行的分支。
推荐阅读
- mysql - 需要将数据从我的 PC 上的 MySQL DB 带到 Snowflake
- c# - RavenDb 空间查询
- r - 如何正确拟合三个参数 t 分布?
- node.js - 使用 axios 制作 Azure Zip Deploy
- javascript - 无法在 ReactJS 中完美地使用 CSS 中的位置
- javascript - 如何创建定义了 clientX 和 clientY 的鼠标事件
- pdf - 是否有任何 pdf 分析器/调试器来调试 pdf 文件?
- c# - 显示另一个类datagridview中的一个类的数据c#
- architecture - 微服务依赖架构设计模式 - 我如何实际组织我的依赖关系?
- visual-studio - VS 2019 Enterprise:找不到“分析所有测试的代码覆盖率”选项