Skip to content

Commit bdbfa49

Browse files
committed
C++ destructors: Ensure "this" is a fully qualified name
Typechecking does not magically expand `ID_this`, and there isn't sufficient context to use "cpp-this." Fixes: diffblue#661
1 parent 4a277c4 commit bdbfa49

File tree

4 files changed

+26
-28
lines changed

4 files changed

+26
-28
lines changed

regression/cbmc-cpp/cpp1/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.cpp
3-
3+
--unwind 1 --unwinding-assertions
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

src/cpp/cpp_typecheck.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ class cpp_typecheckt:public c_typecheck_baset
257257

258258
void default_dtor(const symbolt &symb, cpp_declarationt &dtor);
259259

260-
codet dtor(const symbolt &symb);
260+
codet dtor(const symbolt &symb, const symbol_exprt &this_expr);
261261

262262
void check_member_initializers(
263263
const struct_typet::basest &bases,

src/cpp/cpp_typecheck_destructor.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void cpp_typecheckt::default_dtor(
4747
}
4848

4949
/// produces destructor code for a class object
50-
codet cpp_typecheckt::dtor(const symbolt &symbol)
50+
codet cpp_typecheckt::dtor(const symbolt &symbol, const symbol_exprt &this_expr)
5151
{
5252
assert(symbol.type.id()==ID_struct ||
5353
symbol.type.id()==ID_union);
@@ -85,7 +85,7 @@ codet cpp_typecheckt::dtor(const symbolt &symbol)
8585

8686
exprt ptrmember(ID_ptrmember);
8787
ptrmember.set(ID_component_name, c.get_name());
88-
ptrmember.operands().push_back(exprt("cpp-this"));
88+
ptrmember.operands().push_back(this_expr);
8989

9090
code_assignt assign(ptrmember, address);
9191
block.add(assign);
@@ -113,8 +113,7 @@ codet cpp_typecheckt::dtor(const symbolt &symbol)
113113

114114
exprt member(ID_ptrmember, type);
115115
member.set(ID_component_cpp_name, cppname);
116-
member.operands().push_back(
117-
symbol_exprt(ID_this, pointer_type(symbol.type)));
116+
member.operands().push_back(this_expr);
118117
member.add_source_location() = source_location;
119118

120119
const bool disabled_access_control = disable_access_control;
@@ -139,8 +138,7 @@ codet cpp_typecheckt::dtor(const symbolt &symbol)
139138
DATA_INVARIANT(bit->id() == ID_base, "base class expression expected");
140139
const symbolt &psymb = lookup(bit->type());
141140

142-
symbol_exprt this_ptr(ID_this, pointer_type(symbol.type));
143-
dereference_exprt object(this_ptr, psymb.type);
141+
dereference_exprt object{this_expr, psymb.type};
144142
object.add_source_location() = source_location;
145143

146144
const bool disabled_access_control = disable_access_control;

src/cpp/cpp_typecheck_function.cpp

+19-19
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,6 @@ void cpp_typecheckt::convert_function(symbolt &symbol)
9090
if(symbol.value.is_nil())
9191
return;
9292

93-
// if it is a destructor, add the implicit code
94-
if(to_code_type(symbol.type).return_type().id() == ID_destructor)
95-
{
96-
const symbolt &msymb=lookup(symbol.type.get(ID_C_member_name));
97-
98-
assert(symbol.value.id()==ID_code);
99-
assert(symbol.value.get(ID_statement)==ID_block);
100-
101-
if(
102-
!symbol.value.has_operands() || !symbol.value.op0().has_operands() ||
103-
symbol.value.op0().op0().id() != ID_already_typechecked)
104-
{
105-
symbol.value.copy_to_operands(dtor(msymb));
106-
}
107-
}
108-
10993
// enter appropriate scope
11094
cpp_save_scopet saved_scope(cpp_scopes);
11195
cpp_scopet &function_scope=cpp_scopes.set_scope(symbol.name);
@@ -123,13 +107,29 @@ void cpp_typecheckt::convert_function(symbolt &symbol)
123107
code_typet::parameterst &parameters=function_type.parameters();
124108
assert(parameters.size()>=1);
125109
code_typet::parametert &this_parameter_expr=parameters.front();
126-
function_scope.this_expr=exprt(ID_symbol, this_parameter_expr.type());
127-
function_scope.this_expr.set(
128-
ID_identifier, this_parameter_expr.get_identifier());
110+
function_scope.this_expr = symbol_exprt{
111+
this_parameter_expr.get_identifier(), this_parameter_expr.type()};
129112
}
130113
else
131114
function_scope.this_expr.make_nil();
132115

116+
// if it is a destructor, add the implicit code
117+
if(to_code_type(symbol.type).return_type().id() == ID_destructor)
118+
{
119+
const symbolt &msymb = lookup(symbol.type.get(ID_C_member_name));
120+
121+
assert(symbol.value.id() == ID_code);
122+
assert(symbol.value.get(ID_statement) == ID_block);
123+
124+
if(
125+
!symbol.value.has_operands() || !symbol.value.op0().has_operands() ||
126+
symbol.value.op0().op0().id() != ID_already_typechecked)
127+
{
128+
symbol.value.copy_to_operands(
129+
dtor(msymb, to_symbol_expr(function_scope.this_expr)));
130+
}
131+
}
132+
133133
// do the function body
134134
start_typecheck_code();
135135

0 commit comments

Comments
 (0)