Hi! libtsan atomics aren't throwing, so if we transform atomics which are throwing with -fnon-call-exceptions, we need to clean up EH stuff.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-03-20 Jakub Jelinek <ja...@redhat.com> PR sanitizer/80110 * tsan.c: Include tree-eh.h. (instrument_builtin_call): Call maybe_clean_eh_stmt or maybe_clean_or_replace_eh_stmt where needed. (instrument_memory_accesses): Add cfg_changed argument. Call gimple_purge_dead_eh_edges on each block and set *cfg_changed if it returned true. (tsan_pass): Adjust caller. Return TODO_cleanup_cfg if cfg_changed. * g++.dg/tsan/pr80110.C: New test. --- gcc/tsan.c.jj 2017-03-20 17:55:25.000000000 +0100 +++ gcc/tsan.c 2017-03-20 19:43:34.715321105 +0100 @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. #include "tree-iterator.h" #include "tree-ssa-propagate.h" #include "tree-ssa-loop-ivopts.h" +#include "tree-eh.h" #include "tsan.h" #include "asan.h" #include "builtins.h" @@ -504,6 +505,7 @@ instrument_builtin_call (gimple_stmt_ite return; gimple_call_set_fndecl (stmt, decl); update_stmt (stmt); + maybe_clean_eh_stmt (stmt); if (tsan_atomic_table[i].action == fetch_op) { args[1] = gimple_call_arg (stmt, 1); @@ -524,6 +526,7 @@ instrument_builtin_call (gimple_stmt_ite ? MEMMODEL_SEQ_CST : MEMMODEL_ACQUIRE); update_gimple_call (gsi, decl, num + 1, args[0], args[1], args[2]); + maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); stmt = gsi_stmt (*gsi); if (tsan_atomic_table[i].action == fetch_op_seq_cst) { @@ -572,6 +575,7 @@ instrument_builtin_call (gimple_stmt_ite return; update_gimple_call (gsi, decl, 5, args[0], args[1], args[2], args[4], args[5]); + maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); return; case bool_cas: case val_cas: @@ -599,6 +603,7 @@ instrument_builtin_call (gimple_stmt_ite MEMMODEL_SEQ_CST), build_int_cst (NULL_TREE, MEMMODEL_SEQ_CST)); + maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); if (tsan_atomic_table[i].action == val_cas && lhs) { tree cond; @@ -623,6 +628,7 @@ instrument_builtin_call (gimple_stmt_ite build_int_cst (t, 0), build_int_cst (NULL_TREE, MEMMODEL_RELEASE)); + maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); return; case bool_clear: case bool_test_and_set: @@ -651,11 +657,13 @@ instrument_builtin_call (gimple_stmt_ite { update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0), build_int_cst (t, 0), last_arg); + maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); return; } t = build_int_cst (t, targetm.atomic_test_and_set_trueval); update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0), t, last_arg); + maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); stmt = gsi_stmt (*gsi); lhs = gimple_call_lhs (stmt); if (lhs == NULL_TREE) @@ -766,7 +774,7 @@ instrument_func_exit (void) Return true if func entry/exit should be instrumented. */ static bool -instrument_memory_accesses (void) +instrument_memory_accesses (bool *cfg_changed) { basic_block bb; gimple_stmt_iterator gsi; @@ -775,20 +783,24 @@ instrument_memory_accesses (void) auto_vec<gimple *> tsan_func_exits; FOR_EACH_BB_FN (bb, cfun) - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple *stmt = gsi_stmt (gsi); - if (gimple_call_internal_p (stmt, IFN_TSAN_FUNC_EXIT)) - { - if (fentry_exit_instrument) - replace_func_exit (stmt); - else - tsan_func_exits.safe_push (stmt); - func_exit_seen = true; - } - else - fentry_exit_instrument |= instrument_gimple (&gsi); - } + { + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (gimple_call_internal_p (stmt, IFN_TSAN_FUNC_EXIT)) + { + if (fentry_exit_instrument) + replace_func_exit (stmt); + else + tsan_func_exits.safe_push (stmt); + func_exit_seen = true; + } + else + fentry_exit_instrument |= instrument_gimple (&gsi); + } + if (gimple_purge_dead_eh_edges (bb)) + *cfg_changed = true; + } unsigned int i; gimple *stmt; FOR_EACH_VEC_ELT (tsan_func_exits, i, stmt) @@ -835,9 +847,10 @@ static unsigned tsan_pass (void) { initialize_sanitizer_builtins (); - if (instrument_memory_accesses ()) + bool cfg_changed = false; + if (instrument_memory_accesses (&cfg_changed)) instrument_func_entry (); - return 0; + return cfg_changed ? TODO_cleanup_cfg : 0; } /* Inserts __tsan_init () into the list of CTORs. */ --- gcc/testsuite/g++.dg/tsan/pr80110.C.jj 2017-03-20 19:51:02.525497662 +0100 +++ gcc/testsuite/g++.dg/tsan/pr80110.C 2017-03-20 19:50:14.000000000 +0100 @@ -0,0 +1,16 @@ +// PR sanitizer/80110 +// { dg-do compile } +// { dg-options "-fnon-call-exceptions -fsanitize=thread" } + +struct A +{ + int b (); + void c () { static int d = b (); } +}; + +void +foo () +{ + A e; + e.c (); +} Jakub