annotate lld/docs/missingkeyfunction.rst @ 259:011663b4a808

remove duplicate setjmp in return continuation
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 12 Oct 2023 15:52:37 +0900
parents 1d019706d866
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 Missing Key Function
anatofuz
parents:
diff changeset
2 ====================
anatofuz
parents:
diff changeset
3
anatofuz
parents:
diff changeset
4 If your build failed with a linker error something like this::
anatofuz
parents:
diff changeset
5
anatofuz
parents:
diff changeset
6 foo.cc:28: error: undefined reference to 'vtable for C'
anatofuz
parents:
diff changeset
7 the vtable symbol may be undefined because the class is missing its key function
anatofuz
parents:
diff changeset
8 (see https://lld.llvm.org/missingkeyfunction)
anatofuz
parents:
diff changeset
9
anatofuz
parents:
diff changeset
10 it's likely that your class C has a key function (defined by the ABI as the first
anatofuz
parents:
diff changeset
11 non-pure, non-inline, virtual function), but you haven't actually defined it.
anatofuz
parents:
diff changeset
12
anatofuz
parents:
diff changeset
13 When a class has a key function, the compiler emits the vtable (and some other
anatofuz
parents:
diff changeset
14 things as well) only in the translation unit that defines that key function. Thus,
anatofuz
parents:
diff changeset
15 if you're missing the key function, you'll also be missing the vtable. If no other
anatofuz
parents:
diff changeset
16 function calls your missing function, you won't see any undefined reference errors
anatofuz
parents:
diff changeset
17 for it, but you will see undefined references to the vtable symbol.
anatofuz
parents:
diff changeset
18
anatofuz
parents:
diff changeset
19 When a class has no non-pure, non-inline, virtual functions, there is no key
anatofuz
parents:
diff changeset
20 function, and the compiler is forced to emit the vtable in every translation unit
anatofuz
parents:
diff changeset
21 that references the class. In this case, it is emitted in a COMDAT section,
anatofuz
parents:
diff changeset
22 which allows the linker to eliminate all duplicate copies. This is still
anatofuz
parents:
diff changeset
23 wasteful in terms of object file size and link time, so it's always advisable to
anatofuz
parents:
diff changeset
24 ensure there is at least one eligible function that can serve as the key function.
anatofuz
parents:
diff changeset
25
anatofuz
parents:
diff changeset
26 Here are the most common mistakes that lead to this error:
anatofuz
parents:
diff changeset
27
anatofuz
parents:
diff changeset
28 Failing to define a virtual destructor
anatofuz
parents:
diff changeset
29 --------------------------------------
anatofuz
parents:
diff changeset
30
anatofuz
parents:
diff changeset
31 Say you have a base class declared in a header file::
anatofuz
parents:
diff changeset
32
anatofuz
parents:
diff changeset
33 class B {
anatofuz
parents:
diff changeset
34 public:
anatofuz
parents:
diff changeset
35 B();
anatofuz
parents:
diff changeset
36 virtual ~B();
anatofuz
parents:
diff changeset
37 ...
anatofuz
parents:
diff changeset
38 };
anatofuz
parents:
diff changeset
39
anatofuz
parents:
diff changeset
40 Here, ``~B`` is the first non-pure, non-inline, virtual function, so it is the key
anatofuz
parents:
diff changeset
41 function. If you forget to define ``B::~B`` in your source file, the compiler will
anatofuz
parents:
diff changeset
42 not emit the vtable for ``B``, and you'll get an undefined reference to "vtable
anatofuz
parents:
diff changeset
43 for B".
anatofuz
parents:
diff changeset
44
anatofuz
parents:
diff changeset
45 This is just an example of the more general mistake of forgetting to define the
anatofuz
parents:
diff changeset
46 key function, but it's quite common because virtual destructors are likely to be
anatofuz
parents:
diff changeset
47 the first eligible key function and it's easy to forget to implement them. It's
anatofuz
parents:
diff changeset
48 also more likely that you won't have any direct references to the destructor, so
anatofuz
parents:
diff changeset
49 you won't see any undefined reference errors that point directly to the problem.
anatofuz
parents:
diff changeset
50
anatofuz
parents:
diff changeset
51 The solution in this case is to implement the missing function.
anatofuz
parents:
diff changeset
52
anatofuz
parents:
diff changeset
53 Forgetting to declare a virtual function in an abstract class as pure
anatofuz
parents:
diff changeset
54 ---------------------------------------------------------------------
anatofuz
parents:
diff changeset
55
anatofuz
parents:
diff changeset
56 Say you have an abstract base class declared in a header file::
anatofuz
parents:
diff changeset
57
anatofuz
parents:
diff changeset
58 class A {
anatofuz
parents:
diff changeset
59 public:
anatofuz
parents:
diff changeset
60 A();
anatofuz
parents:
diff changeset
61 virtual ~A() {}
anatofuz
parents:
diff changeset
62 virtual int foo() = 0;
anatofuz
parents:
diff changeset
63 ...
anatofuz
parents:
diff changeset
64 virtual int bar();
anatofuz
parents:
diff changeset
65 ...
anatofuz
parents:
diff changeset
66 };
anatofuz
parents:
diff changeset
67
anatofuz
parents:
diff changeset
68 This base class is intended to be abstract, but you forgot to mark one of the
anatofuz
parents:
diff changeset
69 functions pure. Here, ``A::bar``, being non-pure, is nominated as the key function,
anatofuz
parents:
diff changeset
70 and as a result, the vtable for ``A`` is not emitted, because the compiler is
anatofuz
parents:
diff changeset
71 waiting for a translation unit that defines ``A::bar``.
anatofuz
parents:
diff changeset
72
anatofuz
parents:
diff changeset
73 The solution in this case is to add the missing ``= 0`` to the declaration of
anatofuz
parents:
diff changeset
74 ``A::bar``.
anatofuz
parents:
diff changeset
75
anatofuz
parents:
diff changeset
76 Key function is defined, but the linker doesn't see it
anatofuz
parents:
diff changeset
77 ------------------------------------------------------
anatofuz
parents:
diff changeset
78
anatofuz
parents:
diff changeset
79 It's also possible that you have defined the key function somewhere, but the
anatofuz
parents:
diff changeset
80 object file containing the definition of that function isn't being linked into
anatofuz
parents:
diff changeset
81 your application.
anatofuz
parents:
diff changeset
82
anatofuz
parents:
diff changeset
83 The solution in this case is to check your dependencies to make sure that
anatofuz
parents:
diff changeset
84 the object file or the library file containing the key function is given to
anatofuz
parents:
diff changeset
85 the linker.