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.