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

            Bug ID: 102198
           Summary: Unused and nonsensical template instantiations used
                    for return type inference end up in the output
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: blubban at gmail dot com
  Target Milestone: ---

Input:

template<int* x>
int* a() { return x; }

template<int* x>
auto b() { return a<x>; }

template<bool q>
auto c() -> int* (*)()
{
    static int x1;
    return b<&x1>();
}

int main(int argc, char** argv)
{
    if constexpr (false)
    {
        static int x2;
        b<&x2>();
    }
    c<true>();
    c<false>();
}

Compile with -O0.

Expected output: Compiles and links successfully.

Actual output, as of 7.2 through 11.2: Assembly output contains four
instantiations of a(), using template arguments c<true>::x1, c<false>::x1,
main::x2, and c<template argument 1>::x1 (or whatever _ZZ1cIXT_EEPFPivEvE2x1 is
supposed to be, c++filt doesn't like it). There's no storage assigned for the
latter two, so they instantiations throw linker errors.

/opt/compiler-explorer/gcc-11.2.0/bin/../lib/gcc/x86_64-linux-gnu/11.2.0/../../../../x86_64-linux-gnu/bin/ld:
/tmp/cc2i7eNg.o: in function `_Z1aIXadL_ZZ1cIXT_EEPFPivEvE2x1EEES1_v':
<source>:2: undefined reference to `_ZZ1cIXT_EEPFPivEvE2x1'
/opt/compiler-explorer/gcc-11.2.0/bin/../lib/gcc/x86_64-linux-gnu/11.2.0/../../../../x86_64-linux-gnu/bin/ld:
/tmp/cc2i7eNg.o: in function `int* a<&(main::x2)>()':
<source>:2: undefined reference to `main::x2'
collect2: error: ld returned 1 exit status

Actual output, as of current trunk:

<source>: In instantiation of 'auto b() [with int* x = (& x1)]':
<source>:5:6:   required from here
<source>:5:6: internal compiler error: in discriminator_for_local_entity, at
cp/mangle.c:1965
    5 | auto b() { return a<x>; }
      |      ^
0x1f31a39 internal_error(char const*, ...)
        ???:0
0x79e1c7 fancy_abort(char const*, int, char const*)
        ???:0
0x8fe32b mangle_decl(tree_node*)
        ???:0
0x148f6b2 decl_assembler_name(tree_node*)
        ???:0
0x14c15d0 assign_assembler_name_if_needed(tree_node*)
        ???:0
0xc38855 cgraph_node::analyze()
        ???:0
0xc3cfdd symbol_table::finalize_compilation_unit()
        ???:0
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

The issues go away if I change main to  if constexpr (true)  or remove the
template from c(), if I put x1 and x2 in global scope, if I append  -> int*
(*)()  to b(), or if I enable -O1 or higher. Only the template variant gives
ICE,  if constexpr (false)  gives the same bad output in trunk as in 11.2
(after removing or neutralizing c()).

I don't know how many different issues this is, but they all look like
different facets of the same root cause (either the extra a() instantiations
should be discarded after determining b's return type, or they shouldn't be
created at all), so I'm filing one bug for them all.

Compiler Explorer: https://godbolt.org/z/89794xb8v

Reply via email to