Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
Version 7.1

10/15/26 [GH #309]
Position of (lowered) cleanups at the end of a function body

The cleanup actions (e.g., destructor calls) performed when control reaches
the end of a function body were attributed to the source position of the
preceding statement instead of to that of the closing brace of the function
body. That is now fixed. For example:

int v = 0;
struct D { ~D() { v = v + 1; } };
void f() {
D d;
v = 2;
} // The call of d's destructor is now positioned on this line.
// Previously it was positioned on the line with "v = 2;" above.


10/9/26 [GH #260]
GNU and Clang C++ modes: members skipped by a designated initializer

Expand Down
27 changes: 21 additions & 6 deletions src/lower_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -19288,12 +19288,27 @@ Lower an stmk_return statement.
} /* if */
if (any_cleanup_on_return) {
/* Generate any cleanup actions required on exit from the routine. */
if (make_block) {
/* Turn the return into a block so that code can be inserted
in front of the return. */
turn_branch_into_block(statement, &insert_location, &return_statement);
} /* if */
gen_cleanup_actions(innermost_function_scope->lifetime, &insert_location);
{ Value_saver<a_source_position> saved_code_pos(&code_pos_for_lowering);
Value_saver<a_source_position> saved_error_position(&error_position);

if (statement->compiler_generated && statement->position.seq == 0) {
a_statement_ptr assoc_block = innermost_function_scope->assoc_block;
if (assoc_block != NULL &&
assoc_block->kind == stmk_block &&
assoc_block->variant.block.extra_info->final_position.seq != 0) {
code_pos_for_lowering = assoc_block->variant.block.extra_info
->final_position;
error_position = code_pos_for_lowering;
} /* if */
} /* if */
if (make_block) {
/* Turn the return into a block so that code can be inserted
in front of the return. */
turn_branch_into_block(statement, &insert_location, &return_statement);
} /* if */
gen_cleanup_actions(innermost_function_scope->lifetime,
&insert_location);
}
reset_cleanup_state_at_transfer_of_control(return_statement, statement);
} /* if */
/* Maintain a list of all returns in the routine so that epilogue code
Expand Down
2 changes: 2 additions & 0 deletions tests/expectations/edg_x86_32_cp/regressions.log
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
gh-309.sft.cpp:fp:-DTEST_NUMBER=1 --g++:REQUIREMENTS NOT MET:
gh-309.sft.cpp:fp:-DTEST_NUMBER=2 --g++ --no_exceptions:REQUIREMENTS NOT MET:
immediate-pragma-lost.sft.cpp:cppbe:-DTEST_NUMBER=1:PASS:
pragma-il-class-no-lowering.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
pragma-il-class.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
2 changes: 2 additions & 0 deletions tests/expectations/edg_x86_64_cp/regressions.log
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
gh-309.sft.cpp:fp:-DTEST_NUMBER=1 --g++:REQUIREMENTS NOT MET:
gh-309.sft.cpp:fp:-DTEST_NUMBER=2 --g++ --no_exceptions:REQUIREMENTS NOT MET:
immediate-pragma-lost.sft.cpp:cppbe:-DTEST_NUMBER=1:PASS:
pragma-il-class-no-lowering.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
pragma-il-class.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
4 changes: 4 additions & 0 deletions tests/tests/regressions/.gh-309.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fe_only -DTEST_NUMBER=1 --g++ Test_name.c
destructor call on line 14
destructor call on line 18
destructor call on line 20
4 changes: 4 additions & 0 deletions tests/tests/regressions/.gh-309.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fe_only -DTEST_NUMBER=2 --g++ --no_exceptions Test_name.c
destructor call on line 14
destructor call on line 18
destructor call on line 20
20 changes: 20 additions & 0 deletions tests/tests/regressions/gh-309.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//type:fp
//options:--g++:--g++ --no_exceptions
//require:BACK_END_IS_C_GEN_BE 1
//filter:awk '/^#(line)? [0-9]+/ { line = $2; next } /_ZN1DD1Ev\(\(/ { print "destructor call on line " line } { line++ }' Test_name.int.c
int sink;

struct D {
~D();
};

void f() {
D d;
sink = 1;
} // The destructor call was previously attributed to the line above.

void g(bool b) {
D d;
if (b) return;
sink = 2;
} // The destructor call was previously attributed to the line above.