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

Reply via email to