函数模板的section属性在GCC中被忽略
section attribute of a function template is silently ignored in GCC
我试图将一组特定的函数放在一个单独的部分中,但在使用GCC时遇到了问题。
namespace /* anonymous */ {
[[gnu::section(".mysection")]]
void regular_func() { }
template <class T>
[[gnu::section(".mysection")]]
void template_func() { }
} // namespace /* anonymous */
void (*ptr1)() = ®ular_func;
void (*ptr2)() = &template_func<int>;
使用clang,regular_func
和template_func<int>
的符号都被放置在.mysection
中,正如我所期望的那样。
$ clang++ -std=c++14 a.cpp -c && objdump -t a.o | grep -E "regular|template"
0000000000000000 l F .mysection 0000000000000006 _ZN12_GLOBAL__N_112regular_funcEv
0000000000000010 l F .mysection 0000000000000006 _ZN12_GLOBAL__N_113template_funcIiEEvv
但是对于GCC,函数模板不是放在.mysection
中,而是放在.text.*
部分中。
$ g++ -std=c++14 a.cpp -c && objdump -t a.o | grep -E "regular|template"
0000000000000000 l F .mysection 0000000000000007 _ZN12_GLOBAL__N_112regular_funcEv
0000000000000000 l F .text 0000000000000007 _ZN12_GLOBAL__N_113template_funcIiEEvv
我使用的是clang-3.7.1和gcc-5.3.0。
如何强制gcc将模板实例化的函数放在单独的部分中?
这可能是一个小小的安慰,但如果您应用section
,GCC将起作用归因于CCD_ 7的显式实例化,对于要实例化的每个T
,例如
namespace /* anonymous */ {
[[gnu::section(".mysection")]]
void regular_func() { }
template <class T>
void template_func() { }
template [[gnu::section(".mysection")]] void template_func<int>();
} // namespace /* anonymous */
void (*ptr1)() = ®ular_func;
void (*ptr2)() = &template_func<int>;
然后:
$ g++ -std=c++14 a.cpp -c && objdump -C -t a.o | grep -E "regular|template"
0000000000000000 l F .mysection 0000000000000007 (anonymous namespace)::regular_func()
0000000000000007 l F .mysection 0000000000000007 void (anonymous namespace)::template_func<int>()
不幸的是clang拒绝:
template [[gnu::section(".mysection")]] void template_func<int>();
说:
template [[gnu::section(".mysection")]] void template_func<int>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: an attribute list cannot appear here
因此,每个编译器都必须有自己的方式,通过条件编译。
此外,这个修复程序带来了额外的头痛,你必须以某种方式确保template_func()
不能为任何未明确表示的T
实例化实例化。
您可以通过在函数模板的主体中静态断言T
是您允许实例化的类型A,B,C...
之一。那么如果如果T
=D
被实例化,则static_assert
将被激发;你可以将D
添加到列表中,并为D
:添加显式实例化
#include <type_traits>
template<typename T, typename First>
constexpr bool is_in()
{
return std::is_same<T,First>::value;
}
template<typename T, typename First, typename Second, typename ...Rest>
constexpr bool is_in()
{
return is_in<T,First>() || is_in<T,Second,Rest...>();
}
namespace /* anonymous */ {
[[gnu::section(".mysection")]]
void regular_func() { }
template <class T>
void template_func()
{
static_assert(is_in<T,int,float>(),"");
}
template [[gnu::section(".mysection")]] void template_func<int>();
template [[gnu::section(".mysection")]] void template_func<float>();
} // namespace /* anonymous */
void (*ptr1)() = ®ular_func;
void (*ptr2)() = &template_func<int>;
void (*ptr3)() = &template_func<float>;
void (*ptr4)() = &template_func<char>; // <-- static_assert fails
这不是最优雅的方法,但您可以进行一些名称篡改并修改链接器脚本以获得所需的行为
#define TEMPLATE_SECTION(name, section) name##_##section##_
#define template_func TEMPLATE_SECTION(template_func, mysection)
template<class T>
void template_func() { }
void regular_func() {}
int main() {
regular_func(); //placed in ".text"
template_func<int>(); //placed in ".mysection"
template_func<float>(); //placed in ".mysection"
return 0;
}
在链接器脚本中
SECTIONS {
.mysection : {
*(*_mysection_*)
}
.text : {
*(.text .text.*)
}
}
相关文章:
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 奇怪的结构&GCC&clang(void*返回类型)
- GCC本机矩阵运算库
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- gcc和c++17的过载解析失败
- 数据成员SFINAE的C++17测试:gcc vs clang
- GCC对可能有效的代码抛出init list生存期警告
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 使用gcc从静态链接的文件中查找可选符号
- 普通环路未使用gcc 4.8.5自动矢量化
- 有了gcc,是否可以链接库,但前提是它存在
- 在clang++预处理器中确定gcc工具链版本
- 为什么 gcc 编译这个而 msvc 没有
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- gcc - 使用 #pragma 将 __attribute__((section( ".dflash_code" ))) 应用于整个源文件
- 函数模板的section属性在GCC中被忽略
- gcc objdump - what is section .ARM.exidx.text