Skip to content

Commit 04a8c35

Browse files
author
Daniel Kroening
authored
Merge pull request #2334 from tautschnig/c++-virtual
C++: fix virtual table construction
2 parents 0216dbd + 4637f87 commit 04a8c35

7 files changed

+58
-66
lines changed

regression/cpp/virtual1/main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <cassert>
2-
#include <cstdio>
1+
#include <assert.h>
2+
#include <stdio.h>
33

44
class base
55
{

regression/cpp/virtual1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.cpp
33

44
^EXIT=0$

src/cpp/cpp_typecheck_compound_type.cpp

+32-46
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,7 @@ void cpp_typecheckt::typecheck_compound_declarator(
356356
throw 0;
357357
}
358358

359-
if(is_constructor &&
360-
base_name!=id2string(symbol.base_name))
359+
if(is_constructor && base_name != symbol.base_name)
361360
{
362361
error().source_location=cpp_name.source_location();
363362
error() << "member function must return a value or void" << eom;
@@ -425,7 +424,7 @@ void cpp_typecheckt::typecheck_compound_declarator(
425424
}
426425

427426
if(is_typedef)
428-
component.set("is_type", true);
427+
component.set(ID_is_type, true);
429428

430429
if(is_mutable)
431430
component.set("is_mutable", true);
@@ -448,7 +447,7 @@ void cpp_typecheckt::typecheck_compound_declarator(
448447
virtual_name+="$const";
449448

450449
if(has_volatile(method_qualifier))
451-
virtual_name+="$virtual";
450+
virtual_name += "$volatile";
452451

453452
if(component.type().get(ID_return_type)==ID_destructor)
454453
virtual_name="@dtor";
@@ -491,22 +490,18 @@ void cpp_typecheckt::typecheck_compound_declarator(
491490
component.type().set("#virtual_name", virtual_name);
492491

493492
// Check if it is a pure virtual method
494-
if(is_virtual)
493+
if(value.is_not_nil() && value.id() == ID_constant)
495494
{
496-
if(value.is_not_nil() && value.id()==ID_constant)
495+
mp_integer i;
496+
to_integer(value, i);
497+
if(i!=0)
497498
{
498-
mp_integer i;
499-
to_integer(value, i);
500-
if(i!=0)
501-
{
502-
error().source_location=declarator.name().source_location();
503-
error() << "expected 0 to mark pure virtual method, got "
504-
<< i << eom;
505-
throw 0;
506-
}
507-
component.set("is_pure_virtual", true);
508-
value.make_nil();
499+
error().source_location = declarator.name().source_location();
500+
error() << "expected 0 to mark pure virtual method, got " << i << eom;
501+
throw 0;
509502
}
503+
component.set("is_pure_virtual", true);
504+
value.make_nil();
510505
}
511506

512507
typecheck_member_function(
@@ -615,47 +610,36 @@ void cpp_typecheckt::typecheck_compound_declarator(
615610

616611
// do the body of the function
617612
typecast_exprt late_cast(
613+
lookup(args[0].get(ID_C_identifier)).symbol_expr(),
618614
to_code_type(component.type()).parameters()[0].type());
619615

620-
late_cast.op0()=
621-
namespacet(symbol_table).lookup(
622-
args[0].get(ID_C_identifier)).symbol_expr();
616+
side_effect_expr_function_callt expr_call;
617+
expr_call.function() =
618+
symbol_exprt(component.get_name(), component.type());
619+
expr_call.arguments().reserve(args.size());
620+
expr_call.arguments().push_back(late_cast);
621+
622+
for(const auto &arg : args)
623+
{
624+
expr_call.arguments().push_back(
625+
lookup(arg.get(ID_C_identifier)).symbol_expr());
626+
}
623627

624628
if(code_type.return_type().id()!=ID_empty &&
625629
code_type.return_type().id()!=ID_destructor)
626630
{
627-
side_effect_expr_function_callt expr_call;
628-
expr_call.function()=
629-
symbol_exprt(component.get_name(), component.type());
630631
expr_call.type()=to_code_type(component.type()).return_type();
631-
expr_call.arguments().reserve(args.size());
632-
expr_call.arguments().push_back(late_cast);
632+
exprt already_typechecked(ID_already_typechecked);
633+
already_typechecked.move_to_operands(expr_call);
633634

634-
for(std::size_t i=1; i < args.size(); i++)
635-
{
636-
expr_call.arguments().push_back(
637-
namespacet(symbol_table).lookup(
638-
args[i].get(ID_C_identifier)).symbol_expr());
639-
}
640-
641-
func_symb.value=code_returnt(expr_call);
635+
func_symb.value = code_returnt(already_typechecked).make_block();
642636
}
643637
else
644638
{
645-
code_function_callt code_func;
646-
code_func.function()=
647-
symbol_exprt(component.get_name(), component.type());
648-
code_func.arguments().reserve(args.size());
649-
code_func.arguments().push_back(late_cast);
639+
exprt already_typechecked(ID_already_typechecked);
640+
already_typechecked.move_to_operands(expr_call);
650641

651-
for(std::size_t i=1; i < args.size(); i++)
652-
{
653-
code_func.arguments().push_back(
654-
namespacet(symbol_table).lookup(
655-
args[i].get(ID_C_identifier)).symbol_expr());
656-
}
657-
658-
func_symb.value=code_func;
642+
func_symb.value = code_expressiont(already_typechecked).make_block();
659643
}
660644

661645
// add this new function to the list of components
@@ -671,6 +655,8 @@ void cpp_typecheckt::typecheck_compound_declarator(
671655
CHECK_RETURN(!failed);
672656
}
673657

658+
put_compound_into_scope(new_compo);
659+
674660
// next base
675661
virtual_bases.erase(virtual_bases.begin());
676662
}

src/cpp/cpp_typecheck_constructor.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -297,12 +297,10 @@ void cpp_typecheckt::default_cpctor(
297297
cppname.move_to_sub(name);
298298

299299
const symbolt &virtual_table_symbol_type =
300-
namespacet(symbol_table).lookup(
301-
mem_it->type().subtype().get(ID_identifier));
300+
lookup(mem_it->type().subtype().get(ID_identifier));
302301

303-
const symbolt &virtual_table_symbol_var =
304-
namespacet(symbol_table).lookup(
305-
id2string(virtual_table_symbol_type.name) + "@" +
302+
const symbolt &virtual_table_symbol_var = lookup(
303+
id2string(virtual_table_symbol_type.name) + "@" +
306304
id2string(symbol.name));
307305

308306
exprt var=virtual_table_symbol_var.symbol_expr();

src/cpp/cpp_typecheck_destructor.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,11 @@ codet cpp_typecheckt::dtor(const symbolt &symbol)
8989
cppname.move_to_sub(name);
9090

9191
const symbolt &virtual_table_symbol_type =
92-
namespacet(symbol_table).lookup(
93-
cit->type().subtype().get(ID_identifier));
92+
lookup(cit->type().subtype().get(ID_identifier));
9493

95-
const symbolt &virtual_table_symbol_var =
96-
namespacet(symbol_table).lookup(
97-
id2string(virtual_table_symbol_type.name)+"@"+id2string(symbol.name));
94+
const symbolt &virtual_table_symbol_var = lookup(
95+
id2string(virtual_table_symbol_type.name) + "@" +
96+
id2string(symbol.name));
9897

9998
exprt var=virtual_table_symbol_var.symbol_expr();
10099
address_of_exprt address(var);

src/cpp/cpp_typecheck_function.cpp

+13-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ void cpp_typecheckt::convert_parameter(
3434

3535
parameter.set_identifier(identifier);
3636

37+
// the parameter may already have been set up if dealing with virtual methods
38+
const symbolt *check_symbol;
39+
if(!lookup(identifier, check_symbol))
40+
return;
41+
3742
symbolt symbol;
3843

3944
symbol.name=identifier;
@@ -93,7 +98,12 @@ void cpp_typecheckt::convert_function(symbolt &symbol)
9398
assert(symbol.value.id()==ID_code);
9499
assert(symbol.value.get(ID_statement)==ID_block);
95100

96-
symbol.value.copy_to_operands(dtor(msymb));
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+
}
97107
}
98108

99109
// enter appropriate scope
@@ -168,9 +178,9 @@ irep_idt cpp_typecheckt::function_identifier(const typet &type)
168178
const typet &pointer=it->type();
169179
const typet &symbol =pointer.subtype();
170180
if(symbol.get_bool(ID_C_constant))
171-
result+="const$";
181+
result += "$const";
172182
if(symbol.get_bool(ID_C_volatile))
173-
result+="volatile$";
183+
result += "$volatile";
174184
result+="this";
175185
first=false;
176186
it++;

src/cpp/cpp_typecheck_virtual_table.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ void cpp_typecheckt::do_virtual_table(const symbolt &symbol)
6161
{
6262
const std::map<irep_idt, exprt> &value_map=cit->second;
6363

64-
const symbolt &late_cast_symb=namespacet(symbol_table).lookup(cit->first);
65-
const symbolt &vt_symb_type=
66-
namespacet(symbol_table).lookup(
67-
"virtual_table::"+id2string(late_cast_symb.name));
64+
const symbolt &late_cast_symb = lookup(cit->first);
65+
const symbolt &vt_symb_type =
66+
lookup("virtual_table::" + id2string(late_cast_symb.name));
6867

6968
symbolt vt_symb_var;
7069
vt_symb_var.name=

0 commit comments

Comments
 (0)