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

--- Comment #7 from prathamesh3492 at gcc dot gnu.org ---
Created attachment 41313
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41313&action=edit
untested fix

Hi,
The issue can be reproduced with following test-case:

char f(void)
{
  char *a();
  void bar(char *);

  char d = *a();
  char *p = __builtin_strdup (&d);
  __builtin_free (p);
  bar (&d);
}

cddce1 marks the call to __builtin_strdup as necessary:
marking necessary through .MEM_6 stmt p_7 = __builtin_strdup (&d);

and since p_7 doesn't get added to worklist in propagate_necessity
because it's used only within free(), it's treated as "dead"
and wrongly gets released.
The patch fixes that by adding strdup/strndup in corresponding condition
in eliminate_unnecessary_stmts.

I am not sure though why call to strdup is marked necessary.
I suppose it's safe to remove calls to strdup and free in above case since
strdup won't modify d ?

Another issue I found was that my patch failed to remove multiple calls to
strdup:
char *f(char **tt)
{
  char *t = *tt;
  char *p;

  p = __builtin_strdup (t);
  p = __builtin_strdup (t);
  return p;
}

That's fixed in patch by adding strdup/strndup to another corresponding
condition in propagate_necessity
so that only one instance of strdup would be kept.

Validation in progress, will post it to the list if it passes.

Thanks,
Prathamesh

Reply via email to