Hi! The following testcase fails with -fcompare-debug, because we have a bb containing 2 ASAN_MARK (POISON, ...) calls immediately after each other, followed with -g only by debug stmts till end of basic block. sanitize_asan_mark_poison walks stmts in a bb backwards and assumes (incorrectly) that gsi_remove will move the iterator backwards too, but it moves it forward (and if removing stmt at the end of bb turns it into gsi end). The effect is that with -g, we remove both ASAN_MARK calls (desirable), because after the first removal gsi is moved to the following debug stmt which we do nothing about once again and get to the first ASAN_MARK, but with -g0 gsi becomes end and we don't remove anything further from the bb after removing the last stmt.
Fixed by copying the iterator to a copy, gsi_prev and then gsi_remove on the copy. The rest is just cleanup, I think we don't need the bool vars when we can easily continue; instead. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-12-16 Jakub Jelinek <ja...@redhat.com> PR sanitizer/78832 * sanopt.c (sanitize_asan_mark_unpoison): Remove next variable, use continue if gsi_next should be skipped. (sanitize_asan_mark_poison): Remove prev variable, use continue if gsi_prev should be skipped. When removing ASAN_MARK, do gsi_prev first and gsi_remove on a previously made copy of the iterator. * gcc.dg/asan/pr78832.c: New test. --- gcc/sanopt.c.jj 2016-12-14 20:28:14.000000000 +0100 +++ gcc/sanopt.c 2016-12-16 17:08:03.016432304 +0100 @@ -740,7 +740,6 @@ sanitize_asan_mark_unpoison (void) gimple_stmt_iterator gsi; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) { - bool next = true; gimple *stmt = gsi_stmt (gsi); if (gimple_call_internal_p (stmt, IFN_ASAN_MARK)) { @@ -753,12 +752,11 @@ sanitize_asan_mark_unpoison (void) unlink_stmt_vdef (stmt); release_defs (stmt); gsi_remove (&gsi, true); - next = false; + continue; } } - if (next) - gsi_next (&gsi); + gsi_next (&gsi); } } } @@ -840,7 +838,6 @@ sanitize_asan_mark_poison (void) gimple_stmt_iterator gsi; for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);) { - bool prev = true; gimple *stmt = gsi_stmt (gsi); if (maybe_contains_asan_check (stmt)) break; @@ -850,12 +847,13 @@ sanitize_asan_mark_poison (void) fprintf (dump_file, "Removing ASAN_MARK poison\n"); unlink_stmt_vdef (stmt); release_defs (stmt); - gsi_remove (&gsi, true); - prev = false; + gimple_stmt_iterator gsi2 = gsi; + gsi_prev (&gsi); + gsi_remove (&gsi2, true); + continue; } - if (prev) - gsi_prev (&gsi); + gsi_prev (&gsi); } } } --- gcc/testsuite/gcc.dg/asan/pr78832.c.jj 2016-12-16 17:22:27.446280214 +0100 +++ gcc/testsuite/gcc.dg/asan/pr78832.c 2016-12-16 17:23:17.117638783 +0100 @@ -0,0 +1,22 @@ +/* PR sanitizer/78832 */ +/* { dg-do compile } */ +/* { dg-additional-options "-fcompare-debug" } */ + +void bar (int *); + +int +foo (int x) +{ + int *f = 0; + if (x) + goto lab; + { + int y, z; + bar (&y); + int *d = &y; + bar (&z); + int *e = &z; + } + f = &x; + lab: return 6; +} Jakub