<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Fri, 21 Dec 2018 at 11:28, Rui Ueyama via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ruiu<br>
Date: Fri Dec 21 11:28:49 2018<br>
New Revision: 349941<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=349941&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=349941&view=rev</a><br>
Log:<br>
Add a doc for missing key function and an error message referencing the doc.<br>
<br>
Summary:<br>
This is a common error, and because many people don't know what the key<br>
function is, it is sometimes very confusing.<br>
<br>
The doc was originally written by Brooks Moses and slightly edited by me.<br>
<br>
Reviewers: MaskRay, espindola<br>
<br>
Subscribers: emaste, llvm-commits, arichardson<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D55968" rel="noreferrer" target="_blank">https://reviews.llvm.org/D55968</a><br>
<br>
Added:<br>
    lld/trunk/docs/missingkeymethod.rst<br>
Modified:<br>
    lld/trunk/ELF/Relocations.cpp<br>
    lld/trunk/test/ELF/undef.s<br>
<br>
Modified: lld/trunk/ELF/Relocations.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=349941&r1=349940&r2=349941&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=349941&r1=349940&r2=349941&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Relocations.cpp (original)<br>
+++ lld/trunk/ELF/Relocations.cpp Fri Dec 21 11:28:49 2018<br>
@@ -663,6 +663,10 @@ static bool maybeReportUndefined(Symbol<br>
     Msg += Src + "\n>>>               ";<br>
   Msg += Sec.getObjMsg(Offset);<br>
<br>
+  if (Sym.getName().startswith("_ZTV"))<br>
+    Msg += "\nthe vtable symbol may be undefined because the class is missing "<br>
+           "its key function (see <a href="https://lld.llvm.org/missingkeymethod" rel="noreferrer" target="_blank">https://lld.llvm.org/missingkeymethod</a>)";<br></blockquote><div><br></div><div>We should call this page missingkeyfunction not missingkeymethod. (There is no such thing as a "method" in C++.)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
   if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) ||<br>
       Config->NoinhibitExec) {<br>
     warn(Msg);<br>
<br>
Added: lld/trunk/docs/missingkeymethod.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/docs/missingkeymethod.rst?rev=349941&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/docs/missingkeymethod.rst?rev=349941&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/docs/missingkeymethod.rst (added)<br>
+++ lld/trunk/docs/missingkeymethod.rst Fri Dec 21 11:28:49 2018<br>
@@ -0,0 +1,84 @@<br>
+Missing Key Method<br>
+==================<br>
+<br>
+If your build failed with a linker error something like this::<br>
+<br>
+  foo.cc:28: error: undefined reference to 'vtable for C'<br>
+  the vtable symbol may be undefined because the class is missing its key function (see <a href="https://lld.llvm.org/missingkeymethod" rel="noreferrer" target="_blank">https://lld.llvm.org/missingkeymethod</a>)<br>
+<br>
+it's likely that your class C has a key method (defined by the ABI as the first<br>
+non-pure, non-inline, virtual method), but you haven't actually defined it.<br>
+<br>
+When a class has a key method, the compiler emits the vtable (and some other<br>
+things as well) only in the translation unit that defines that key method. Thus,<br>
+if you're missing the key method, you'll also be missing the vtable. If no other<br>
+function calls your missing method, you won't see any undefined reference errors<br>
+for it, but you will see undefined references to the vtable symbol.<br>
+<br>
+When a class has no non-pure, non-inline, virtual methods, there is no key<br>
+method, and the compiler is forced to emit the vtable in every translation unit<br>
+that references the class. In this case, it is emitted in a COMDAT section,<br>
+which allows the linker to eliminate all duplicate copies. This is still<br>
+wasteful in terms of object file size and link time, so it's always advisable to<br>
+ensure there is at least one eligible method that can serve as the key method.<br>
+<br>
+Here are the most common mistakes that lead to this error:<br>
+<br>
+Failing to define a virtual destructor<br>
+--------------------------------------<br>
+<br>
+Say you have a base class declared in a header file::<br>
+<br>
+  class B {<br>
+  public:<br>
+    B();<br>
+    virtual ~B();<br>
+    ...<br>
+  };<br>
+<br>
+Here, ``~B`` is the first non-pure, non-inline, virtual method, so it is the key<br>
+method. If you forget to define ``B::~B`` in your source file, the compiler will<br>
+not emit the vtable for ``B``, and you'll get an undefined reference to "vtable<br>
+for B".<br>
+<br>
+This is just an example of the more general mistake of forgetting to define the<br>
+key method, but it's quite common because virtual destructors are likely to be<br>
+the first eligible key method and it's easy to forget to implement them. It's<br>
+also more likely that you won't have any direct references to the destructor, so<br>
+you won't see any undefined reference errors that point directly to the problem.<br>
+<br>
+The solution in this case is to implement the missing method.<br>
+<br>
+Forgetting to declare a virtual method in an abstract class as pure<br>
+-------------------------------------------------------------------<br>
+<br>
+Say you have an abstract base class declared in a header file::<br>
+<br>
+  class A {<br>
+  public:<br>
+    A();<br>
+    virtual ~A() {}<br>
+    virtual int foo() = 0;<br>
+    ...<br>
+    virtual int bar();<br>
+    ...<br>
+  };<br>
+<br>
+This base class is intended to be abstract, but you forgot to mark one of the<br>
+methods pure. Here, ``A::bar``, being non-pure, is nominated as the key method,<br>
+and as a result, the vtable for ``A`` is not emitted, because the compiler is<br>
+waiting for a translation unit that defines ``A::bar``.<br>
+<br>
+The solution in this case is to add the missing ``= 0`` to the declaration of<br>
+``A::bar``.<br>
+<br>
+Key method is defined, but the linker doesn't see it<br>
+----------------------------------------------------<br>
+<br>
+It's also possible that you have defined the key method somewhere, but the<br>
+object file containing the definition of that method isn't being linked into<br>
+your application.<br>
+<br>
+The solution in this case is to check your dependencies to make sure that<br>
+the object file or the library file containing the key method is given to<br>
+the linker.<br>
<br>
Modified: lld/trunk/test/ELF/undef.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/undef.s?rev=349941&r1=349940&r2=349941&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/undef.s?rev=349941&r1=349940&r2=349941&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/undef.s (original)<br>
+++ lld/trunk/test/ELF/undef.s Fri Dec 21 11:28:49 2018<br>
@@ -20,6 +20,9 @@<br>
 # CHECK: >>> referenced by undef.s<br>
 # CHECK: >>>               {{.*}}:(.text+0x10)<br>
<br>
+# CHECK: error: undefined symbol: vtable for Foo<br>
+# CHECK: the vtable symbol may be undefined because the class is missing its key function (see <a href="https://lld.llvm.org/missingkeymethod" rel="noreferrer" target="_blank">https://lld.llvm.org/missingkeymethod</a>)<br>
+<br>
 # CHECK: error: undefined symbol: zed2<br>
 # CHECK: >>> referenced by {{.*}}.o:(.text+0x0) in archive {{.*}}2.a<br>
<br>
@@ -60,3 +63,4 @@ _start:<br>
   call bar<br>
   call zed1<br>
   call _Z3fooi<br>
+  call _ZTV3Foo<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>