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