150
|
1 RUN: lld-link -lldmingw %S/Inputs/inline-weak.o %S/Inputs/inline-weak2.o -out:%t.exe
|
|
2
|
|
3 When compiling certain forms of templated inline functions, some
|
|
4 versions of GCC (tested with 5.4) produces a weak symbol for the function.
|
|
5 Newer versions of GCC don't do this though.
|
|
6
|
|
7 The bundled object files are an example of that, they can be produced
|
|
8 with test code like this:
|
|
9
|
|
10 $ cat inline-weak.h
|
|
11 class MyClass {
|
|
12 public:
|
|
13 template<typename... _Args> int get(_Args&&... args) {
|
|
14 return a;
|
|
15 }
|
|
16 private:
|
|
17 int a;
|
|
18 };
|
|
19
|
|
20 $ cat inline-weak.cpp
|
|
21 #include "inline-weak.h"
|
|
22
|
|
23 int get(MyClass& a);
|
|
24
|
|
25 int main(int argc, char* argv[]) {
|
|
26 MyClass a;
|
|
27 int ret = a.get();
|
|
28 ret += get(a);
|
|
29 return ret;
|
|
30 }
|
|
31 extern "C" void mainCRTStartup(void) {
|
|
32 main(0, (char**)0);
|
|
33 }
|
|
34 extern "C" void __main(void) {
|
|
35 }
|
|
36
|
|
37 $ cat inline-weak2.cpp
|
|
38 #include "inline-weak.h"
|
|
39
|
|
40 int get(MyClass& a) {
|
|
41 return a.get();
|
|
42 }
|
|
43
|
|
44 $ x86_64-w64-mingw32-g++ -std=c++11 -c inline-weak.cpp
|
|
45 $ x86_64-w64-mingw32-g++ -std=c++11 -c inline-weak2.cpp
|
|
46
|
|
47 $ x86_64-w64-mingw32-nm inline-weak.o | grep MyClass3get
|
|
48 0000000000000000 p .pdata$_ZN7MyClass3getIJEEEiDpOT_
|
|
49 0000000000000000 t .text$_ZN7MyClass3getIJEEEiDpOT_
|
|
50 0000000000000000 T .weak._ZN7MyClass3getIIEEEiDpOT_.main
|
|
51 0000000000000000 r .xdata$_ZN7MyClass3getIJEEEiDpOT_
|
|
52 w _ZN7MyClass3getIIEEEiDpOT_
|
|
53 0000000000000000 T _ZN7MyClass3getIJEEEiDpOT_
|
|
54
|
|
55 $ x86_64-w64-mingw32-nm inline-weak2.o | grep MyClass3get
|
|
56 0000000000000000 p .pdata$_ZN7MyClass3getIJEEEiDpOT_
|
|
57 0000000000000000 t .text$_ZN7MyClass3getIJEEEiDpOT_
|
|
58 0000000000000000 T .weak._ZN7MyClass3getIIEEEiDpOT_._Z3getR7MyClass
|
|
59 0000000000000000 r .xdata$_ZN7MyClass3getIJEEEiDpOT_
|
|
60 w _ZN7MyClass3getIIEEEiDpOT_
|
|
61 0000000000000000 T _ZN7MyClass3getIJEEEiDpOT_
|
|
62
|
|
63 This can't be reproduced by assembling .s files with llvm-mc, since that
|
|
64 always produces a symbol named .weak.<weaksymbol>.default, therefore
|
|
65 the test uses prebuilt object files instead.
|
|
66
|
|
67 In these cases, the undefined weak symbol points to the regular symbol
|
|
68 .weak._ZN7MyClass3getIIEEEiDpOT_.<othersymbol>, where <othersymbol>
|
|
69 varies among the object files that emit the same function. This regular
|
|
70 symbol points to the same location as the comdat function
|
|
71 _ZN7MyClass3getIJEEEiDpOT_.
|
|
72
|
|
73 When linking, the comdat section from the second object file gets
|
|
74 discarded, as it matches the one that already exists. This means that
|
|
75 the uniquely named symbol .weak.<weakname>.<othername> points to a
|
|
76 discarded section chunk.
|
|
77
|
|
78 Previously, this would have triggered adding an Undefined symbol for
|
|
79 this case, which would later break linking. However, also previously,
|
|
80 if the second object file is linked in via a static library, this
|
|
81 leftover symbol is retained as a Lazy symbol, which would make the link
|
|
82 succeed.
|