mirror of git://gcc.gnu.org/git/gcc.git
tree-eh.c (goto_queue_node): New field.
gcc: * tree-eh.c (goto_queue_node): New field. (record_in_goto_queue): New parameter. (record_in_goto_queue_label): New parameter. (lower_try_finally_dup_block): New parameter. (maybe_record_in_goto_queue): Update source location. (lower_try_finally_copy): Likewise. (honor_protect_cleanup_actions): Likewise. * gimplify.c (gimplify_expr): Reset the location to unknown. testsuite: * g++.dg/debug/dwarf2/deallocator.C: New test. libjava: * testsuite/libjava.lang/sourcelocation.java: New cases. * testsuite/libjava.lang/sourcelocation.out: New cases. From-SVN: r191338
This commit is contained in:
parent
71452ccd31
commit
820055a0ac
|
|
@ -1,3 +1,14 @@
|
||||||
|
2012-09-14 Dehao Chen <dehao@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_dup_block): New parameter.
|
||||||
|
(maybe_record_in_goto_queue): Update source location.
|
||||||
|
(lower_try_finally_copy): Likewise.
|
||||||
|
(honor_protect_cleanup_actions): Likewise.
|
||||||
|
* gimplify.c (gimplify_expr): Reset the location to unknown.
|
||||||
|
|
||||||
2012-09-14 David Edelsohn <dje.gcc@gmail.com>
|
2012-09-14 David Edelsohn <dje.gcc@gmail.com>
|
||||||
|
|
||||||
* configure: Regenerated.
|
* configure: Regenerated.
|
||||||
|
|
|
||||||
|
|
@ -7453,6 +7453,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||||
gimple_seq eval, cleanup;
|
gimple_seq eval, cleanup;
|
||||||
gimple try_;
|
gimple try_;
|
||||||
|
|
||||||
|
/* Calls to destructors are generated automatically in FINALLY/CATCH
|
||||||
|
block. They should have location as UNKNOWN_LOCATION. However,
|
||||||
|
gimplify_call_expr will reset these call stmts to input_location
|
||||||
|
if it finds stmt's location is unknown. To prevent resetting for
|
||||||
|
destructors, we set the input_location to unknown.
|
||||||
|
Note that this only affects the destructor calls in FINALLY/CATCH
|
||||||
|
block, and will automatically reset to its original value by the
|
||||||
|
end of gimplify_expr. */
|
||||||
|
input_location = UNKNOWN_LOCATION;
|
||||||
eval = cleanup = NULL;
|
eval = cleanup = NULL;
|
||||||
gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
|
gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
|
||||||
gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
|
gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
2012-09-14 Dehao Chen <dehao@google.com>
|
||||||
|
|
||||||
|
* g++.dg/debug/dwarf2/deallocator.C: New test.
|
||||||
|
|
||||||
2012-09-14 Joseph Myers <joseph@codesourcery.com>
|
2012-09-14 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
PR c/54552
|
PR c/54552
|
||||||
|
|
|
||||||
|
|
@ -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 -dA" }
|
||||||
|
|
||||||
|
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 "deallocator.C:28" } }
|
||||||
|
|
@ -321,6 +321,7 @@ static bitmap eh_region_may_contain_throw_map;
|
||||||
struct goto_queue_node
|
struct goto_queue_node
|
||||||
{
|
{
|
||||||
treemple stmt;
|
treemple stmt;
|
||||||
|
location_t location;
|
||||||
gimple_seq repl_stmt;
|
gimple_seq repl_stmt;
|
||||||
gimple cont_stmt;
|
gimple cont_stmt;
|
||||||
int index;
|
int index;
|
||||||
|
|
@ -560,7 +561,8 @@ static void
|
||||||
record_in_goto_queue (struct leh_tf_state *tf,
|
record_in_goto_queue (struct leh_tf_state *tf,
|
||||||
treemple new_stmt,
|
treemple new_stmt,
|
||||||
int index,
|
int index,
|
||||||
bool is_label)
|
bool is_label,
|
||||||
|
location_t location)
|
||||||
{
|
{
|
||||||
size_t active, size;
|
size_t active, size;
|
||||||
struct goto_queue_node *q;
|
struct goto_queue_node *q;
|
||||||
|
|
@ -583,6 +585,7 @@ record_in_goto_queue (struct leh_tf_state *tf,
|
||||||
memset (q, 0, sizeof (*q));
|
memset (q, 0, sizeof (*q));
|
||||||
q->stmt = new_stmt;
|
q->stmt = new_stmt;
|
||||||
q->index = index;
|
q->index = index;
|
||||||
|
q->location = location;
|
||||||
q->is_label = is_label;
|
q->is_label = is_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -590,7 +593,8 @@ record_in_goto_queue (struct leh_tf_state *tf,
|
||||||
TF is not null. */
|
TF is not null. */
|
||||||
|
|
||||||
static void
|
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,
|
||||||
|
location_t location)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
treemple temp, new_stmt;
|
treemple temp, new_stmt;
|
||||||
|
|
@ -629,7 +633,7 @@ record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label)
|
||||||
since with a GIMPLE_COND we have an easy access to the then/else
|
since with a GIMPLE_COND we have an easy access to the then/else
|
||||||
labels. */
|
labels. */
|
||||||
new_stmt = stmt;
|
new_stmt = stmt;
|
||||||
record_in_goto_queue (tf, new_stmt, index, true);
|
record_in_goto_queue (tf, new_stmt, index, true, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally
|
/* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally
|
||||||
|
|
@ -649,19 +653,22 @@ maybe_record_in_goto_queue (struct leh_state *state, gimple stmt)
|
||||||
{
|
{
|
||||||
case GIMPLE_COND:
|
case GIMPLE_COND:
|
||||||
new_stmt.tp = gimple_op_ptr (stmt, 2);
|
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),
|
||||||
|
EXPR_LOCATION (*new_stmt.tp));
|
||||||
new_stmt.tp = gimple_op_ptr (stmt, 3);
|
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),
|
||||||
|
EXPR_LOCATION (*new_stmt.tp));
|
||||||
break;
|
break;
|
||||||
case GIMPLE_GOTO:
|
case GIMPLE_GOTO:
|
||||||
new_stmt.g = stmt;
|
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_location (stmt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMPLE_RETURN:
|
case GIMPLE_RETURN:
|
||||||
tf->may_return = true;
|
tf->may_return = true;
|
||||||
new_stmt.g = stmt;
|
new_stmt.g = stmt;
|
||||||
record_in_goto_queue (tf, new_stmt, -1, false);
|
record_in_goto_queue (tf, new_stmt, -1, false, gimple_location (stmt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -866,13 +873,19 @@ frob_into_branch_around (gimple tp, eh_region region, tree over)
|
||||||
Make sure to record all new labels found. */
|
Make sure to record all new labels found. */
|
||||||
|
|
||||||
static gimple_seq
|
static gimple_seq
|
||||||
lower_try_finally_dup_block (gimple_seq seq, struct leh_state *outer_state)
|
lower_try_finally_dup_block (gimple_seq seq, struct leh_state *outer_state,
|
||||||
|
location_t loc)
|
||||||
{
|
{
|
||||||
gimple region = NULL;
|
gimple region = NULL;
|
||||||
gimple_seq new_seq;
|
gimple_seq new_seq;
|
||||||
|
gimple_stmt_iterator gsi;
|
||||||
|
|
||||||
new_seq = copy_gimple_seq_and_replace_locals (seq);
|
new_seq = copy_gimple_seq_and_replace_locals (seq);
|
||||||
|
|
||||||
|
for (gsi = gsi_start (new_seq); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||||
|
if (gimple_location (gsi_stmt (gsi)) == UNKNOWN_LOCATION)
|
||||||
|
gimple_set_location (gsi_stmt (gsi), loc);
|
||||||
|
|
||||||
if (outer_state->tf)
|
if (outer_state->tf)
|
||||||
region = outer_state->tf->try_finally_expr;
|
region = outer_state->tf->try_finally_expr;
|
||||||
collect_finally_tree_1 (new_seq, region);
|
collect_finally_tree_1 (new_seq, region);
|
||||||
|
|
@ -967,7 +980,8 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
|
||||||
gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else));
|
gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else));
|
||||||
}
|
}
|
||||||
else if (this_state)
|
else if (this_state)
|
||||||
finally = lower_try_finally_dup_block (finally, outer_state);
|
finally = lower_try_finally_dup_block (finally, outer_state,
|
||||||
|
UNKNOWN_LOCATION);
|
||||||
finally_may_fallthru = gimple_seq_may_fallthru (finally);
|
finally_may_fallthru = gimple_seq_may_fallthru (finally);
|
||||||
|
|
||||||
/* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
|
/* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
|
||||||
|
|
@ -1184,7 +1198,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
|
||||||
|
|
||||||
if (tf->may_fallthru)
|
if (tf->may_fallthru)
|
||||||
{
|
{
|
||||||
seq = lower_try_finally_dup_block (finally, state);
|
seq = lower_try_finally_dup_block (finally, state, tf_loc);
|
||||||
lower_eh_constructs_1 (state, &seq);
|
lower_eh_constructs_1 (state, &seq);
|
||||||
gimple_seq_add_seq (&new_stmt, seq);
|
gimple_seq_add_seq (&new_stmt, seq);
|
||||||
|
|
||||||
|
|
@ -1200,7 +1214,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
|
||||||
if (eh_else)
|
if (eh_else)
|
||||||
seq = gimple_eh_else_e_body (eh_else);
|
seq = gimple_eh_else_e_body (eh_else);
|
||||||
else
|
else
|
||||||
seq = lower_try_finally_dup_block (finally, state);
|
seq = lower_try_finally_dup_block (finally, state, tf_loc);
|
||||||
lower_eh_constructs_1 (state, &seq);
|
lower_eh_constructs_1 (state, &seq);
|
||||||
|
|
||||||
emit_post_landing_pad (&eh_seq, tf->region);
|
emit_post_landing_pad (&eh_seq, tf->region);
|
||||||
|
|
@ -1250,7 +1264,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
|
||||||
x = gimple_build_label (lab);
|
x = gimple_build_label (lab);
|
||||||
gimple_seq_add_stmt (&new_stmt, x);
|
gimple_seq_add_stmt (&new_stmt, x);
|
||||||
|
|
||||||
seq = lower_try_finally_dup_block (finally, state);
|
seq = lower_try_finally_dup_block (finally, state, q->location);
|
||||||
lower_eh_constructs_1 (state, &seq);
|
lower_eh_constructs_1 (state, &seq);
|
||||||
gimple_seq_add_seq (&new_stmt, seq);
|
gimple_seq_add_seq (&new_stmt, seq);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2012-09-14 Dehao Chen <dehao@google.com>
|
||||||
|
|
||||||
|
* testsuite/libjava.lang/sourcelocation.java: New cases.
|
||||||
|
* testsuite/libjava.lang/sourcelocation.out: New cases.
|
||||||
|
|
||||||
2012-09-14 David Edelsohn <dje.gcc@gmail.com>
|
2012-09-14 David Edelsohn <dje.gcc@gmail.com>
|
||||||
|
|
||||||
* configure: Regenerated.
|
* configure: Regenerated.
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* This test should test the source location attribution.
|
||||||
|
We print the line number of different parts of the program to make sure
|
||||||
|
that the source code attribution is correct.
|
||||||
|
To make this test pass, one need to have up-to-date addr2line installed
|
||||||
|
to parse the dwarf4 data format.
|
||||||
|
*/
|
||||||
|
public class sourcelocation {
|
||||||
|
public static void main(String args[]) {
|
||||||
|
try {
|
||||||
|
System.out.println(new Exception().getStackTrace()[0].getLineNumber());
|
||||||
|
throw new Exception();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(new Exception().getStackTrace()[0].getLineNumber());
|
||||||
|
} finally {
|
||||||
|
System.out.println(new Exception().getStackTrace()[0].getLineNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
10
|
||||||
|
13
|
||||||
|
15
|
||||||
Loading…
Reference in New Issue