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'...