<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/74721>74721</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            undefined reference to `vtable for Derived' for exported key function
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          JVApen
      </td>
    </tr>
</table>

<pre>
    This problem is a variation on the problem of https://lld.llvm.org/missingkeyfunction, though none of the solutions mentioned are the problem.

liba.h
````
#pragma once
#define EXPORT __attribute__((visibility("default")))

class Base
{
public:
    Base() = default;
    ~Base() = default;
 virtual void bsf() = 0;
};

class Derived : public Base
{
public:
    Derived() = default;
    ~Derived() = default;
    EXPORT void bsf() override;
};
````

liba.cpp
````
#include "liba.h"

void Derived::bsf()
{

}
````

main.cpp
````
#include "liba.h"

int main()
{
    [[maybe_unused]] auto x = Derived{};
}
````

CMakeLists.txt
````
cmake_minimum_required(VERSION 2.22)

project(visibility)

add_compile_options(-Wall -Wextra -fvisibility=hidden)
add_link_options(-W,-z,defs)

add_library(a SHARED liba.cpp)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE a)
````


>From the command line:
````
> objdump -C -t CMakeFiles/main.dir/main.cpp.o | grep Derived
0000000000000000 l    d  .text._ZN7DerivedC2Ev 0000000000000000 .text._ZN7DerivedC2Ev
0000000000000000  w    F .text._ZN7DerivedC2Ev  0000000000000034 .hidden Derived::Derived()
0000000000000000         *UND*  0000000000000000 vtable for Derived
> objdump -C -t liba.so | grep Derived
0000000000002810 l O .data.rel.ro   0000000000000018              .hidden vtable for Derived
0000000000002828 l     O .data.rel.ro   0000000000000018 .hidden typeinfo for Derived
0000000000000670 l     O .rodata 0000000000000009              .hidden typeinfo name for Derived
00000000000017a0 g     F .text  000000000000000a Derived::bsf()
````
The method Derived::bsf() is the key function ` (defined by the ABI as the first non-pure, non-inline, virtual function)`.
This has a definition in liba.cpp
As the Ctor/Dtor are inline, main.cpp has an implementation of the constructor that requires the vtable.

In the content of the object file liba.so, we can see that Derived::bsf() is an exported function, and the dtor method seems to be created as a hidden function. The vtable also exists. The main.o file requires the symbol for the vtable to exist. On linking, it doesn't find it.

Based on what we read on https://lld.llvm.org/missingkeyfunction, all requirements related to the keyfunction are met. As such, I believe the liba.o file should have the vtable symbol exported such that main.o can use it.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykV0tv67oR_jX0ZmBBph-yF144doymaE8uctNzi24MShxZPKFIlaScuIv-9oLUw4_ESdBrGI4ew2---WaGnDBrxV4hLsn0jkw3A1a7QpvlX3-uKlSDVPPj8rkQFiqjU4klCAsMDswI5oRWoBW4Avu3OofCucqS8YrQLaFbKXkk5aGMtNkTui2FtULtX_CY1yrzCISuwRW63hegtEKP4AGtlrV_baFE5S-QAzN47iwi8YbEq-ZXipRFRftkFp--zRM6rgzblwy0yrB_xjEXCuH-n789Pj3DbsecMyKtHe52hM4JnR-EFamQwh3DPeWYs1o6Qimhi_Z7RiKTzFq4Y7Zzkdw1F1WdSpF5UcItADRWHnQBZLyBDnl8dzL571c2B2FczSQctOCQ2vzMNu6tSLI5XZ_R3KARB-RAxito-H2TebvwK_LfM2u1v4pAH9AYwfHjIN6n91QCWVV9UgRCZbLmCITStmAoPYcINDri4xUZr3pOV7qcaH3KqWRC_UlOQjnwMB_S8BKGxr0r2THFXa1qi5xMN2S6AVY7DW9B-i6m5O5Cya_or__OXvBvwjobuTd3yzYr2QvuSqFEWZc7g_-uhQmJ_3n_9PvD4w-gUdMwZ8iV0b8wc1c9dmHCON9luqyExJ2uwmZA6Hz4B5MShn_gmzMMhvnZ8vGmEJyj6nE8ghTq5WI5oevhfwhdc8ztBx6lSA0zvt8Z_P6X1dP9BvrCem-Nb5jVjqXS96nPEvQZ74wdM3t0DY8GXKDtrH97evi5er4HdsK-kYrmd2t0GfbATJclUxykUNh35wdrx_eg01-8LisYrmHoIKR0K6TnsA1kuTDdZVZVkQaSrGFvsOqrJkDFVx-Qvvg4QOTwzUW7f_1IWvs1vT_AO_MPzW5Aw6vH3t6AvsIeTyBqEn_Zuhcb0C1H7YfQ1T9-bAhdXYPHMRxCfiHX5lKQ99qGQrHfEZDOR17AR4g4cywyKCOj4dr5aA4Xny7MW4wuPdB5k6JveOmA3bFCoXL9OXQ8S-ITtNEe_Fq2xcfMeweKlV8EMEpYDHs4K4R3uWGf79XvuuG5QCjRFfrWJu-nG99dL3iEbkABMouB0HkzLHBIj8FkdfcArLHOhbHOTy_DqjboBxp_LVToTbruj-nTyLMgszjqOAkLBfNTVfAggk-h4PI4WzWu1k77Zt04bcI4dHLS9W-DpUCUlUQ_O7VzWt5uG8o6U2d-vSuYg3a3btCburqYqx5Ut86hch2MTv3mDbmQ2BW95_CKkDEFFrEBvy0yU4BvlTYOOZxPgn5L8w64J9imyiKWFpyGFCEzyPyaoFdbU936CJ77GIBJqwHfwtEVngd9dEP5Imh7LFMtQy2eNPDuwuoIHn0q1ItQe09QOOAarSI08fErDsJdCOZnKO7H4levwKt3xsL9_zEX-5Ou5eozacGgDOE73ZVpX6W-Gkp0Eaws2Dor_PoHSFEKPDRjc0hUq4AtdC05FKx910bdatGnxgM1qWzl8-mtLfqgB3w55ovxgg1wOUri0WIWz-aTQbHM2DSfzUaULXi6yCeU0tk8GdERjROGkykbiCWN6djfjybTEZ1Ei3ESZ_P5fJTHcTJlGZnEWDIhe4UGwtoal8kkoaOBZClKG_5foVThK4SXfmqabgZm6dcM03pvySSWIf89ihNO4rJWXSsbzNGgykK6ySz-YF-lSbjtFTnfGQa1kcvLtO6FK-o0ynQZcnzo_gz7eWcb2PrDN0TzvwAAAP__0aIC4A">