[lld] r349941 - Add a doc for missing key function and an error message referencing the doc.

Richard Smith via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 21 14:36:08 PST 2018


On Fri, 21 Dec 2018 at 11:28, Rui Ueyama via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: ruiu
> Date: Fri Dec 21 11:28:49 2018
> New Revision: 349941
>
> URL: http://llvm.org/viewvc/llvm-project?rev=349941&view=rev
> Log:
> Add a doc for missing key function and an error message referencing the
> doc.
>
> Summary:
> This is a common error, and because many people don't know what the key
> function is, it is sometimes very confusing.
>
> The doc was originally written by Brooks Moses and slightly edited by me.
>
> Reviewers: MaskRay, espindola
>
> Subscribers: emaste, llvm-commits, arichardson
>
> Differential Revision: https://reviews.llvm.org/D55968
>
> Added:
>     lld/trunk/docs/missingkeymethod.rst
> Modified:
>     lld/trunk/ELF/Relocations.cpp
>     lld/trunk/test/ELF/undef.s
>
> Modified: lld/trunk/ELF/Relocations.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=349941&r1=349940&r2=349941&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Relocations.cpp (original)
> +++ lld/trunk/ELF/Relocations.cpp Fri Dec 21 11:28:49 2018
> @@ -663,6 +663,10 @@ static bool maybeReportUndefined(Symbol
>      Msg += Src + "\n>>>               ";
>    Msg += Sec.getObjMsg(Offset);
>
> +  if (Sym.getName().startswith("_ZTV"))
> +    Msg += "\nthe vtable symbol may be undefined because the class is
> missing "
> +           "its key function (see https://lld.llvm.org/missingkeymethod
> )";
>

We should call this page missingkeyfunction not missingkeymethod. (There is
no such thing as a "method" in C++.)


> +
>    if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn &&
> CanBeExternal) ||
>        Config->NoinhibitExec) {
>      warn(Msg);
>
> Added: lld/trunk/docs/missingkeymethod.rst
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/docs/missingkeymethod.rst?rev=349941&view=auto
>
> ==============================================================================
> --- lld/trunk/docs/missingkeymethod.rst (added)
> +++ lld/trunk/docs/missingkeymethod.rst Fri Dec 21 11:28:49 2018
> @@ -0,0 +1,84 @@
> +Missing Key Method
> +==================
> +
> +If your build failed with a linker error something like this::
> +
> +  foo.cc:28: error: undefined reference to 'vtable for C'
> +  the vtable symbol may be undefined because the class is missing its key
> function (see https://lld.llvm.org/missingkeymethod)
> +
> +it's likely that your class C has a key method (defined by the ABI as the
> first
> +non-pure, non-inline, virtual method), but you haven't actually defined
> it.
> +
> +When a class has a key method, the compiler emits the vtable (and some
> other
> +things as well) only in the translation unit that defines that key
> method. Thus,
> +if you're missing the key method, you'll also be missing the vtable. If
> no other
> +function calls your missing method, you won't see any undefined reference
> errors
> +for it, but you will see undefined references to the vtable symbol.
> +
> +When a class has no non-pure, non-inline, virtual methods, there is no key
> +method, and the compiler is forced to emit the vtable in every
> translation unit
> +that references the class. In this case, it is emitted in a COMDAT
> section,
> +which allows the linker to eliminate all duplicate copies. This is still
> +wasteful in terms of object file size and link time, so it's always
> advisable to
> +ensure there is at least one eligible method that can serve as the key
> method.
> +
> +Here are the most common mistakes that lead to this error:
> +
> +Failing to define a virtual destructor
> +--------------------------------------
> +
> +Say you have a base class declared in a header file::
> +
> +  class B {
> +  public:
> +    B();
> +    virtual ~B();
> +    ...
> +  };
> +
> +Here, ``~B`` is the first non-pure, non-inline, virtual method, so it is
> the key
> +method. If you forget to define ``B::~B`` in your source file, the
> compiler will
> +not emit the vtable for ``B``, and you'll get an undefined reference to
> "vtable
> +for B".
> +
> +This is just an example of the more general mistake of forgetting to
> define the
> +key method, but it's quite common because virtual destructors are likely
> to be
> +the first eligible key method and it's easy to forget to implement them.
> It's
> +also more likely that you won't have any direct references to the
> destructor, so
> +you won't see any undefined reference errors that point directly to the
> problem.
> +
> +The solution in this case is to implement the missing method.
> +
> +Forgetting to declare a virtual method in an abstract class as pure
> +-------------------------------------------------------------------
> +
> +Say you have an abstract base class declared in a header file::
> +
> +  class A {
> +  public:
> +    A();
> +    virtual ~A() {}
> +    virtual int foo() = 0;
> +    ...
> +    virtual int bar();
> +    ...
> +  };
> +
> +This base class is intended to be abstract, but you forgot to mark one of
> the
> +methods pure. Here, ``A::bar``, being non-pure, is nominated as the key
> method,
> +and as a result, the vtable for ``A`` is not emitted, because the
> compiler is
> +waiting for a translation unit that defines ``A::bar``.
> +
> +The solution in this case is to add the missing ``= 0`` to the
> declaration of
> +``A::bar``.
> +
> +Key method is defined, but the linker doesn't see it
> +----------------------------------------------------
> +
> +It's also possible that you have defined the key method somewhere, but the
> +object file containing the definition of that method isn't being linked
> into
> +your application.
> +
> +The solution in this case is to check your dependencies to make sure that
> +the object file or the library file containing the key method is given to
> +the linker.
>
> Modified: lld/trunk/test/ELF/undef.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/undef.s?rev=349941&r1=349940&r2=349941&view=diff
>
> ==============================================================================
> --- lld/trunk/test/ELF/undef.s (original)
> +++ lld/trunk/test/ELF/undef.s Fri Dec 21 11:28:49 2018
> @@ -20,6 +20,9 @@
>  # CHECK: >>> referenced by undef.s
>  # CHECK: >>>               {{.*}}:(.text+0x10)
>
> +# CHECK: error: undefined symbol: vtable for Foo
> +# CHECK: the vtable symbol may be undefined because the class is missing
> its key function (see https://lld.llvm.org/missingkeymethod)
> +
>  # CHECK: error: undefined symbol: zed2
>  # CHECK: >>> referenced by {{.*}}.o:(.text+0x0) in archive {{.*}}2.a
>
> @@ -60,3 +63,4 @@ _start:
>    call bar
>    call zed1
>    call _Z3fooi
> +  call _ZTV3Foo
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181221/eb93d3f2/attachment.html>


More information about the llvm-commits mailing list