Skip to content

Commit 446d656

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: #661
1 parent c09873b commit 446d656

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
@@ -92,22 +92,6 @@ void cpp_typecheckt::convert_function(symbolt &symbol)
9292
if(symbol.value.is_nil())
9393
return;
9494

95-
// if it is a destructor, add the implicit code
96-
if(to_code_type(symbol.type).return_type().id() == ID_destructor)
97-
{
98-
const symbolt &msymb=lookup(symbol.type.get(ID_C_member_name));
99-
100-
assert(symbol.value.id()==ID_code);
101-
assert(symbol.value.get(ID_statement)==ID_block);
102-
103-
if(
104-
!symbol.value.has_operands() || !symbol.value.op0().has_operands() ||
105-
symbol.value.op0().op0().id() != ID_already_typechecked)
106-
{
107-
symbol.value.copy_to_operands(dtor(msymb));
108-
}
109-
}
110-
11195
// enter appropriate scope
11296
cpp_save_scopet saved_scope(cpp_scopes);
11397
cpp_scopet &function_scope=cpp_scopes.set_scope(symbol.name);
@@ -125,13 +109,29 @@ void cpp_typecheckt::convert_function(symbolt &symbol)
125109
code_typet::parameterst &parameters=function_type.parameters();
126110
assert(parameters.size()>=1);
127111
code_typet::parametert &this_parameter_expr=parameters.front();
128-
function_scope.this_expr=exprt(ID_symbol, this_parameter_expr.type());
129-
function_scope.this_expr.set(
130-
ID_identifier, this_parameter_expr.get_identifier());
112+
function_scope.this_expr =
113+
symbol_exprt{
114+
this_parameter_expr.get_identifier(), this_parameter_expr.type()};
131115
}
132116
else
133117
function_scope.this_expr.make_nil();
134118

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

0 commit comments

Comments
 (0)