我有一些看起来非常不可能的东西.我有三个文件,每个文件似乎都包含完全相同的函数声明,虽然定义不同.
inst_dp_vec2.cc:
void loadSOAFVec(InstVector &ivector,
const FVec &ret,
const Address *a,
int soanum,
int soalen,
string mask) {
if (soalen == 2) {
ivector.push_back(new LoadFVec(ret, a, string("")));
} else {
printf("SOALEN = %d not supported at %s:%d\n", soalen, __FILE__,
__LINE__);
exit(1);
}
}
Run Code Online (Sandbox Code Playgroud)
inst_dp_vec4.cc
void loadSOAFVec(InstVector &ivector,
const FVec &ret,
const Address *a,
int soanum,
int soalen,
string mask) {
if (soalen == 4) {
ivector.push_back(new LoadFVec(ret, a, string("")));
} else if (soalen == 2) {
ivector.push_back(new LoadHalfFVec(ret, a, soanum));
} else {
UNSUPPORTED_SOALEN(soalen);
}
}
Run Code Online (Sandbox Code Playgroud)
inst_dp_vec8.cc
void loadSOAFVec(InstVector &ivector,
const FVec &ret,
const Address *a,
int soanum,
int soalen,
string mask) {
int mskbits = (((1 << soalen) - 1) << (soanum * soalen));
stringstream mk;
mk << "0x" << hex << mskbits;
string localmask = mk.str();
ivector.push_back(new LoadUnpackFVec(ret, a, localmask));
}
Run Code Online (Sandbox Code Playgroud)
从Makefile(由GNU Autotools生成)执行的链接器命令似乎包括所有三个编译文件:
g++ -O3 -g -DNO_HW_MASKING -DUSE_LDUNPK -DUSE_PKST -DUSE_PACKED_GAUGES
-DUSE_PACKED_CLOVER -DNO_GPREF_L1 -DNO_GPREF_L2 -DENABLE_STREAMING_STORES
-DSERIAL_SPIN -DSOALEN=8 -DVECLEN=4 -DPRECISION=2 codegen.o data_types.o
dslash.o dslash_common.o inst_dp_vec8.o inst_sp_vec16.o inst_dp_vec4.o
inst_sp_vec8.o inst_sp_vec4.o inst_dp_vec2.o inst_scalar.o -o codegen
Run Code Online (Sandbox Code Playgroud)
根据我对一个定义规则的了解,这应该给出一个链接器错误.更奇特的是,版本来自inst_dp_vec8.o不是使用的版本,而是来自的版本inst_dp_vec4.cc,尽管它首先出现在链接器命令行中.我更改了代码,以便UNSUPPORTED_SOALEN抛出异常,并且使用GDB我发现它soalen = 8是活动的.根据我对软件的了解,soalen = 8只能使用veclen ? 8只inst_dp_vec8.cc包含正确定义的软件.
我的问题:这可能链接到一个可执行的程序,但由于引发了明确的异常而失败了UNSUPPORTED_SOALEN?
因为在多个翻译单元中出现多个定义时不需要诊断.
来自[basic.def.odr]:
任何翻译单元都不得包含任何变量,函数,类类型,枚举类型或模板的多个定义.
然后
每个程序应该只包含每个非内联函数或变量的一个定义,该函数或变量在废弃语句之外的程序中使用(6.4.1); 无需诊断.
因此,如果它们是源模块中的多个定义,则会出现错误,但如果它们位于不同的模块中,则不必获取它们.