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.

Reply via email to