> > I've tried to see what actually happens during linking without LTO, so > compiled > pr113208_0.C with -O1 -fkeep-inline-functions -std=c++20 with vanilla trunk > (so it has those 2 separate comdats, one for C2 and one for C1), though I've > changed the > void m(k); > line to > __attribute__((noipa)) void m(k) {} > in the testcase, then compiled > pr113208_1.C with -O2 -fkeep-inline-functions -std=c++20 > -fno-omit-frame-pointer > so that one can clearly differentiate from where the implementation was > picked and finally added > template <typename _Tp> struct _Vector_base { > int g() const; > _Vector_base(int, int); > }; > > struct QualityValue; > template <> > _Vector_base<QualityValue>::_Vector_base(int, int) {} > template <> > int _Vector_base<QualityValue>::g() const { return 0; } > int main () {} > If I link this, I see _ZN6vectorI12QualityValueEC2ERKS1_ and > _ZN6vectorI12QualityValueEC1ERKS1_ as separate functions with the > omitted frame pointer bodies, so clearly the pr113208_0.C versions prevailed > in both cases. It is unclear why that isn't the case for LTO.
I think it is because of -fkeep-inline-functions which makes the first object file to define both symbols, while with LTO we optimize out one of them. So to reproduce same behaviour with non-LTO we would probably need use -O1 and arrange the contructor to be unilinable instead of using -fkeep-inline-functions. Honza