Hi, This patch fixes the source location for automatically generated calls to deallocator. For example:
19 void foo(int i) 20 { 21 for (int j = 0; j < 10; j++) 22 { 23 t test; 24 test.foo(); 25 if (i + j) 26 { 27 test.bar(); 28 return; 29 } 30 } 31 return; 32 } The deallocator for "23 t test" is called in two places: Line 28 and line 30. However, gcc attributes both callsites to line 30. Bootstrapped and passed gcc regression tests. Is it ok for trunk? Thanks, Dehao gcc/ChangeLog 2012-07-31 Dehao Chen <de...@google.com> * tree-eh.c (goto_queue_node): New field. (record_in_goto_queue): New parameter. (record_in_goto_queue_label): New parameter. (lower_try_finally_copy): Update source location. gcc/testsuite/ChangeLog 2012-07-31 Dehao Chen <de...@google.com> * g++.dg/guality/deallocator.C: New test. Index: gcc/testsuite/g++.dg/guality/deallocator.C =================================================================== --- gcc/testsuite/g++.dg/guality/deallocator.C (revision 0) +++ gcc/testsuite/g++.dg/guality/deallocator.C (revision 0) @@ -0,0 +1,33 @@ +// Test that debug info generated for auto-inserted deallocator is +// correctly attributed. +// This patch scans for the lineno directly from assembly, which may +// differ between different architectures. Because it mainly tests +// FE generated debug info, without losing generality, only x86 +// assembly is scanned in this test. +// { dg-do compile { target { i?86-*-* x86_64-*-* } } } +// { dg-options "-O2 -fno-exceptions -g" } + +struct t { + t (); + ~t (); + void foo(); + void bar(); +}; + +int bar(); + +void foo(int i) +{ + for (int j = 0; j < 10; j++) + { + t test; + test.foo(); + if (i + j) + { + test.bar(); + return; + } + } + return; +} +// { dg-final { scan-assembler "1 28 0" } } Index: gcc/tree-eh.c =================================================================== --- gcc/tree-eh.c (revision 189835) +++ gcc/tree-eh.c (working copy) @@ -321,6 +321,7 @@ struct goto_queue_node { treemple stmt; + enum gimple_code code; gimple_seq repl_stmt; gimple cont_stmt; int index; @@ -560,7 +561,8 @@ record_in_goto_queue (struct leh_tf_state *tf, treemple new_stmt, int index, - bool is_label) + bool is_label, + enum gimple_code code) { size_t active, size; struct goto_queue_node *q; @@ -583,6 +585,7 @@ memset (q, 0, sizeof (*q)); q->stmt = new_stmt; q->index = index; + q->code = code; q->is_label = is_label; } @@ -590,7 +593,8 @@ TF is not null. */ static void -record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label) +record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label, + enum gimple_code code) { int index; treemple temp, new_stmt; @@ -629,7 +633,7 @@ since with a GIMPLE_COND we have an easy access to the then/else labels. */ new_stmt = stmt; - record_in_goto_queue (tf, new_stmt, index, true); + record_in_goto_queue (tf, new_stmt, index, true, code); } /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally @@ -649,19 +653,22 @@ { case GIMPLE_COND: new_stmt.tp = gimple_op_ptr (stmt, 2); - record_in_goto_queue_label (tf, new_stmt, gimple_cond_true_label (stmt)); + record_in_goto_queue_label (tf, new_stmt, gimple_cond_true_label (stmt), + gimple_code (stmt)); new_stmt.tp = gimple_op_ptr (stmt, 3); - record_in_goto_queue_label (tf, new_stmt, gimple_cond_false_label (stmt)); + record_in_goto_queue_label (tf, new_stmt, gimple_cond_false_label (stmt), + gimple_code (stmt)); break; case GIMPLE_GOTO: new_stmt.g = stmt; - record_in_goto_queue_label (tf, new_stmt, gimple_goto_dest (stmt)); + record_in_goto_queue_label (tf, new_stmt, gimple_goto_dest (stmt), + gimple_code (stmt)); break; case GIMPLE_RETURN: tf->may_return = true; new_stmt.g = stmt; - record_in_goto_queue (tf, new_stmt, -1, false); + record_in_goto_queue (tf, new_stmt, -1, false, gimple_code (stmt)); break; default: @@ -1234,6 +1241,7 @@ for (index = 0; index < return_index + 1; index++) { tree lab; + gimple_stmt_iterator gsi; q = labels[index].q; if (! q) @@ -1252,6 +1260,11 @@ seq = lower_try_finally_dup_block (finally, state); lower_eh_constructs_1 (state, &seq); + for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi)) + gimple_set_location (gsi_stmt (gsi), + q->code == GIMPLE_COND ? + EXPR_LOCATION (*q->stmt.tp) : + gimple_location (q->stmt.g)); gimple_seq_add_seq (&new_stmt, seq); gimple_seq_add_stmt (&new_stmt, q->cont_stmt);