https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323
--- Comment #8 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
(In reply to Patrick Palka from comment #7)
> I noticed we emit the function if we turn it into a non-member:
>
> #include <type_traits>
>
> constexpr int VAL = 1;
>
> template <int B>
> void bar(typename std::conditional<B==VAL, int, float>::type arg) {
> }
>
> template void bar<1>(int arg);
>
> I wonder why this bug seems specific to member functions?
Good question. It's because in this case bar is marked as force_output here:
/* When not optimizing, also output the static functions. (see
PR24561), but don't do so for always_inline functions, functions
declared inline and nested functions. These were optimized out
in the original implementation and it is unclear whether we want
to change the behavior here. */
if (((!opt_for_fn (decl, optimize) || flag_keep_static_functions
|| node->no_reorder)
&& !node->cpp_implicit_alias
&& !DECL_DISREGARD_INLINE_LIMITS (decl)
&& !DECL_DECLARED_INLINE_P (decl)
&& !(DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
node->force_output = 1;
and when deciding if we ought to emit the fn in symtab_node::needed_p we do:
/* If the user told us it is used, then it must be so. */
if (force_output)
return true;
With -O the fn isn't emitted.