https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119369

--- Comment #4 from Thomas Schwinge <tschwinge at gcc dot gnu.org> ---
For the record, the (only?) issue here specifically is '__cxa_pure_virtual', an
'abort'-like function.  This is defined as follows:

'libstdc++-v3/libsupc++/cxxabi.h':

    // Pure virtual functions.
    void
    __cxa_pure_virtual(void) __attribute__ ((__noreturn__));

'libstdc++-v3/libsupc++/pure.cc':

    extern "C" void
    __cxxabiv1::__cxa_pure_virtual (void)
    {
      writestr ("pure virtual method called\n");
      std::terminate ();
    }

..., but is set up in the C++ front end to be referenced "in a weak way", as
follows:

'gcc/cp/cp-tree.h':

    #define abort_fndecl                   cp_global_trees[CPTI_ABORT_FNDECL]

'gcc/cp/decl.cc:cxx_init_decl_processing':

    abort_fndecl
      = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
                       ECF_NORETURN | ECF_NOTHROW | ECF_COLD);
    if (flag_weak)
      /* If no definition is available, resolve references to NULL.  */
      declare_weak (abort_fndecl);

'gcc/cp/class.cc:build_vtbl_initializer':

    /* You can't call an abstract virtual function; it's abstract.
       So, we replace these functions with __pure_virtual.  */
    if (DECL_PURE_VIRTUAL_P (fn_original))
      {
        fn = abort_fndecl;

(Would a (static) linker actually never link in libstdc++/libsupc++ 'pure.o'?)

With '-fno-weak' (or internal GCC/GCN configuration changes to that effect), we
get a non-weak reference, and the libstdc++/libsupc++ definition is linked in;
execution test PASS.

However, GCC/GCN generally does support weak symbols, just not undefined weak
symbols -- similar to GCC/nvptx.


Regarding the latter, I noticed that for this test case, GCC/nvptx emits a
number of other weak symbols (definitions), but for '__cxa_pure_virtual'
specifically emits a non-weak reference:

    .extern .func __cxa_pure_virtual;

(..., and therefore the libstdc++/libsupc++ definition is linked in; PASS.)

How this "works" in GCC/nvptx, is because of
'gcc/config/nvptx/nvptx.cc:write_fn_proto_1':

    if (DECL_EXTERNAL (decl))
      s << ".extern ";
    else if (TREE_PUBLIC (decl) || force_public)
      s << (DECL_WEAK (decl) ? ".weak " : ".visible ");

That is, 'DECL_EXTERNAL' "overrides" 'DECL_WEAK'...

Reply via email to