https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119734
Bug ID: 119734 Summary: nvptx/C++ vs. '_ZTISt8bad_cast' ('typeinfo for std::bad_cast') Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: tschwinge at gcc dot gnu.org Target Milestone: --- Target: nvptx We've got cases of nvptx/C++ code (XFAILed test case soon to appear), where we fail linking due to: unresolved symbol _ZTISt8bad_cast collect2: error: ld returned 1 exit status $ c++filt _ZTISt8bad_cast typeinfo for std::bad_cast That's (a) (I suppose) because we're building libstdc++ with '-fno-rtti', and (b) because GCC/nvptx emits: // BEGIN GLOBAL VAR DECL: _ZTISt8bad_cast .extern .global .align 8 .u64 _ZTISt8bad_cast[3]; ... despite that only being "referenced" within: /* BEGIN '.gcc_except_table' [...] .symbol_ref _ZTISt8bad_cast END '.gcc_except_table' */ It would be good if there was a way to not emit that '.extern' '_ZTISt8bad_cast' declaration if only (fake-)referenced like this. We get that via 'TARGET_ASM_ASSEMBLE_UNDEFINED_DECL' called 'FOR_EACH_VARIABLE' in the symbol table: Breakpoint 7, nvptx_assemble_undefined_decl (file=0x2a8c910, name=0x7ffff783b590 "_ZTISt8bad_cast", decl=0x7ffff78482f8) at ../../source-gcc/gcc/config/nvptx/nvptx.cc:2650 2650 { (gdb) bt #0 nvptx_assemble_undefined_decl (file=0x2a8c910, name=0x7ffff783b590 "_ZTISt8bad_cast", decl=0x7ffff78482f8) at ../../source-gcc/gcc/config/nvptx/nvptx.cc:2650 #1 0x00000000016b83ec in assemble_undefined_decl (decl=0x7ffff78482f8) at ../../source-gcc/gcc/varasm.cc:2458 #2 0x00000000016de6aa in symbol_table::output_variables (this=this@entry=0x7ffff76ef000) at ../../source-gcc/gcc/varpool.cc:766 #3 0x0000000000c81be2 in symbol_table::compile (this=this@entry=0x7ffff76ef000) at ../../source-gcc/gcc/cgraphunit.cc:2421 #4 0x0000000000c855d8 in symbol_table::compile (this=0x7ffff76ef000) at ../../source-gcc/gcc/cgraphunit.cc:2566 #5 symbol_table::finalize_compilation_unit (this=0x7ffff76ef000) at ../../source-gcc/gcc/cgraphunit.cc:2607 #6 0x0000000001267218 in compile_file () at ../../source-gcc/gcc/toplev.cc:479 #7 0x000000000074e32d in do_compile () at ../../source-gcc/gcc/toplev.cc:2208 #8 toplev::main (this=this@entry=0x7fffffffc94e, argc=argc@entry=27, argv=argv@entry=0x7fffffffca78) at ../../source-gcc/gcc/toplev.cc:2371 #9 0x000000000075093b in main (argc=27, argv=0x7fffffffca78) at ../../source-gcc/gcc/main.cc:39 At that time, we can't tell (as far as I can tell) whether we had a "real" reference, or just a "fake" ('.gcc_except_table') one. (Early 'return' if not 'varpool_node::get(decl)->referred_to_p()' does solve this issue, but also regresses other test cases, so that doesn't appear to be the right API, here.) '_ZTISt8bad_cast' gets into the symbol table via: Breakpoint 6, varpool_node::get_create (decl=0x7ffff78482f8) at ../../source-gcc/gcc/varpool.cc:144 144 { (gdb) call debug_tree(decl) <var_decl 0x7ffff78482f8 _ZTISt8bad_cast type <record_type 0x7ffff78601f8 __si_class_type_info_pseudo_9 readonly cxx-odr-p type_5 type_6 BLK size <integer_cst 0x7ffff7849a80 constant 192> unit-size <integer_cst 0x7ffff7849a50 constant 24> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff78601f8 fields <field_decl 0x7ffff784d820 D.2330 type <record_type 0x7ffff7843bd0 __type_info_pseudo_0> BLK <built-in>:0:0 size <integer_cst 0x7ffff76eb948 constant 128> unit-size <integer_cst 0x7ffff76eb960 constant 16> align:64 warn_if_not_align:0 offset_align 128 decl_not_flexarray: 0 offset <integer_cst 0x7ffff76eb930 constant 0> bit-offset <integer_cst 0x7ffff76eb978 constant 0> context <record_type 0x7ffff7860150 __si_class_type_info_pseudo_9> chain <field_decl 0x7ffff784d8c0 D.2331>> full-name "const struct __si_class_type_info_pseudo_9" n_parents=0 use_template=0 interface-unknown pointer_to_this <pointer_type 0x7ffff78602a0>> readonly addressable used public static tree_4 ignored external decl_5 BLK [...]/source-gcc/libstdc++-v3/libsupc++/typeinfo:224:9 size <integer_cst 0x7ffff7849a80 192> unit-size <integer_cst 0x7ffff7849a50 24> align:64 warn_if_not_align:0 context <translation_unit_decl 0x7ffff76ff000 [...]/source-gcc/gcc/testsuite/g++.target/nvptx/exceptions-bad_cast-2_-mfake-exceptions.C> attributes <tree_list 0x7ffff7847050 purpose <identifier_node 0x7ffff7837e80 non overlapping normal local bindings <(nil)>>> chain <var_decl 0x7ffff78481c8 _ZTISt9type_info>> (gdb) bt #0 varpool_node::get_create (decl=0x7ffff78482f8) at ../../source-gcc/gcc/varpool.cc:144 #1 0x0000000000c7d337 in record_type_list (node=node@entry=0x7ffff7875000, list=0x7ffff7879028) at ../../source-gcc/gcc/cgraphbuild.cc:131 #2 0x0000000000c7d43c in record_eh_tables (node=node@entry=0x7ffff7875000, fun=0x7ffff7864410) at ../../source-gcc/gcc/cgraphbuild.cc:171 #3 0x0000000000c7d6b9 in (anonymous namespace)::pass_build_cgraph_edges::execute (this=<optimized out>, fun=0x7ffff7864410) at ../../source-gcc/gcc/cgraphbuild.cc:372 #4 0x000000000111ebdb in execute_one_pass (pass=pass@entry=0x2a7e560) at ../../source-gcc/gcc/passes.cc:2659 #5 0x000000000111f598 in execute_pass_list_1 (pass=0x2a7e560) at ../../source-gcc/gcc/passes.cc:2768 #6 0x000000000111f5f5 in execute_pass_list (fn=<optimized out>, pass=<optimized out>) at ../../source-gcc/gcc/passes.cc:2779 #7 0x0000000000c80b1e in cgraph_node::analyze (this=this@entry=0x7ffff7875000) at ../../source-gcc/gcc/cgraphunit.cc:699 #8 0x0000000000c8461f in analyze_functions (first_time=first_time@entry=true) at ../../source-gcc/gcc/cgraphunit.cc:1265 #9 0x0000000000c854ce in symbol_table::finalize_compilation_unit (this=0x7ffff76ef000) at ../../source-gcc/gcc/cgraphunit.cc:2574 #10 0x0000000001267218 in compile_file () at ../../source-gcc/gcc/toplev.cc:479 #11 0x000000000074e32d in do_compile () at ../../source-gcc/gcc/toplev.cc:2208 #12 toplev::main (this=this@entry=0x7fffffffc94e, argc=argc@entry=27, argv=argv@entry=0x7fffffffca78) at ../../source-gcc/gcc/toplev.cc:2371 #13 0x000000000075093b in main (argc=27, argv=0x7fffffffca78) at ../../source-gcc/gcc/main.cc:39 Further investigation to be done, how to skip this insertion, for example. Probably 'if (in_section == exception_section)' is not useful here. Or, enable '_ZTISt8bad_cast' (etc.?) definition in libstdc++ specifically despite '-fno-rtti', or avoid '-fno-rtti' build of libstdc++ generally.