https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107661
--- Comment #8 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
(In reply to Sergei Trofimovich from comment #7)
> When debug reports unqualified `Aggregate replacements: 1[0]=callback_fn`
> does it mean ipa-cp does not distinguish between:
> * static void function_ref::callback_fn(void*) [with Callable =
> seemingly_unused_foo(int)::L]/30.
> * static void function_ref::callback_fn(void*) [with Callable = void()]/29.
> ?
>
> I suspect it does not and that results in a wrong callback_fn inline.
That was not it. Identical names is a printing artifact.
I shrunk example a bit more to avoid any overloads and crashes. Now example
just prints different things.
// How to break:
// $ ./gcc-13-snap/bin/gcc -O1 -fipa-cp -fipa-cp-clone a.cc -o
a && ./a
// GOOD
// BAD
// $ ./gcc-13-snap/bin/gcc -O1 -fipa-cp -fipa-cp-clone -DDISABLE_HACK a.cc -o a
&& ./a
// GOOD
// GOOD
// #define DISABLE_HACK 1
#include <stdio.h>
struct R {} RGood;
struct L {} LBad;
static void L_run(void) { fprintf(stderr, "BAD\n"); }
static void callback_fn_L(void) { L_run(); }
static void callback_fn_R(void) { fprintf(stderr, "GOOD\n"); }
struct function_ref {
void (*callback)(void) = nullptr;
function_ref(L * pl) { callback = callback_fn_L; }
function_ref(R * pr) { callback = callback_fn_R; }
};
// allow one level of recursion to call callback twice
static int is_recur(void) {
static int n = 0;
switch (n++) {
case 0: return 1;
default: return 0;
}
}
static void do3(volatile int * punused, function_ref Expired) {
Expired.callback();
if (is_recur())
do3(punused, Expired);
}
static void do1(function_ref Expired) {
volatile int unused = 42;
do3(&unused, Expired);
}
int main(void) { do1(&RGood); }
#if defined(DISABLE_HACK)
#else
void seemingly_unused_foo(void) { do1(&LBad); }
#endif