From 3e5190924dfd2b22c6024cb8b10f6d1aa21d9a27 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 25 Jan 2017 15:11:44 +0000 Subject: [PATCH 1/2] Factor class identifier extraction out of remove virtuals This will be useful for other passes that inspect an object's dynamic clsid, such as the forthcoming lower-instanceof pass. --- src/goto-programs/Makefile | 2 +- src/goto-programs/class_identifier.cpp | 88 +++++++++++++++++++ src/goto-programs/class_identifier.h | 21 +++++ .../remove_virtual_functions.cpp | 65 ++------------ 4 files changed, 116 insertions(+), 60 deletions(-) create mode 100644 src/goto-programs/class_identifier.cpp create mode 100644 src/goto-programs/class_identifier.h diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index aa788914562..813be9a18b7 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -17,7 +17,7 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ goto_trace.cpp xml_goto_trace.cpp vcd_goto_trace.cpp \ graphml_witness.cpp remove_virtual_functions.cpp \ class_hierarchy.cpp show_goto_functions.cpp get_goto_model.cpp \ - slice_global_inits.cpp goto_inline_class.cpp + slice_global_inits.cpp goto_inline_class.cpp class_identifier.cpp INCLUDES= -I .. diff --git a/src/goto-programs/class_identifier.cpp b/src/goto-programs/class_identifier.cpp new file mode 100644 index 00000000000..df41fc9c5be --- /dev/null +++ b/src/goto-programs/class_identifier.cpp @@ -0,0 +1,88 @@ +/*******************************************************************\ + +Module: Extract class identifier + +Author: Chris Smowton, chris.smowton@diffblue.com + +\*******************************************************************/ + +#include "class_identifier.h" + +#include + +/*******************************************************************\ + +Function: build_class_identifier + + Inputs: Struct expression + + Outputs: Member expression giving the clsid field of the input, + or its parent, grandparent, etc. + + Purpose: + +\*******************************************************************/ + +static exprt build_class_identifier( + const exprt &src, + const namespacet &ns) +{ + // the class identifier is in the root class + exprt e=src; + + while(1) + { + const typet &type=ns.follow(e.type()); + assert(type.id()==ID_struct); + + const struct_typet &struct_type=to_struct_type(type); + const struct_typet::componentst &components=struct_type.components(); + assert(!components.empty()); + + member_exprt member_expr( + e, + components.front().get_name(), + components.front().type()); + + if(components.front().get_name()=="@class_identifier") + { + // found it + return member_expr; + } + else + { + e=member_expr; + } + } +} + +/*******************************************************************\ + +Function: get_class_identifier_field + + Inputs: Pointer expression of any pointer type, including void*, + and a recommended access type if the pointer is void-typed. + + Outputs: Member expression to access a class identifier, as above. + + Purpose: + +\*******************************************************************/ + +exprt get_class_identifier_field( + exprt this_expr, + const symbol_typet &suggested_type, + const namespacet &ns) +{ + // Get a pointer from which we can extract a clsid. + // If it's already a pointer to an object of some sort, just use it; + // if it's void* then use the suggested type. + + assert(this_expr.type().id()==ID_pointer && + "Non-pointer this-arg in remove-virtuals?"); + const auto& points_to=this_expr.type().subtype(); + if(points_to==empty_typet()) + this_expr=typecast_exprt(this_expr, pointer_typet(suggested_type)); + exprt deref=dereference_exprt(this_expr, this_expr.type().subtype()); + return build_class_identifier(deref, ns); +} diff --git a/src/goto-programs/class_identifier.h b/src/goto-programs/class_identifier.h new file mode 100644 index 00000000000..343a041a547 --- /dev/null +++ b/src/goto-programs/class_identifier.h @@ -0,0 +1,21 @@ +/*******************************************************************\ + +Module: Extract class identifier + +Author: Chris Smowton, chris.smowton@diffblue.com + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H +#define CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H + +#include +#include +#include + +exprt get_class_identifier_field( + exprt this_expr, + const symbol_typet &suggested_type, + const namespacet &ns); + +#endif diff --git a/src/goto-programs/remove_virtual_functions.cpp b/src/goto-programs/remove_virtual_functions.cpp index 4da7d62631b..68c388a8cdf 100644 --- a/src/goto-programs/remove_virtual_functions.cpp +++ b/src/goto-programs/remove_virtual_functions.cpp @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include "class_hierarchy.h" +#include "class_identifier.h" #include "remove_virtual_functions.h" /*******************************************************************\ @@ -61,8 +62,6 @@ class remove_virtual_functionst exprt get_method( const irep_idt &class_id, const irep_idt &component_name) const; - - exprt build_class_identifier(const exprt &); }; /*******************************************************************\ @@ -88,48 +87,6 @@ remove_virtual_functionst::remove_virtual_functionst( /*******************************************************************\ -Function: remove_virtual_functionst::build_class_identifier - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - -exprt remove_virtual_functionst::build_class_identifier( - const exprt &src) -{ - // the class identifier is in the root class - exprt e=src; - - while(1) - { - const typet &type=ns.follow(e.type()); - assert(type.id()==ID_struct); - - const struct_typet &struct_type=to_struct_type(type); - const struct_typet::componentst &components=struct_type.components(); - assert(!components.empty()); - - member_exprt member_expr( - e, components.front().get_name(), components.front().type()); - - if(components.front().get_name()=="@class_identifier") - { - // found it - return member_expr; - } - else - { - e=member_expr; - } - } -} - -/*******************************************************************\ - Function: remove_virtual_functionst::remove_virtual_function Inputs: @@ -181,22 +138,12 @@ void remove_virtual_functionst::remove_virtual_function( goto_programt new_code_calls; goto_programt new_code_gotos; - // Get a pointer from which we can extract a clsid. - // If it's already a pointer to an object of some sort, just use it; - // if it's void* then use the parent of all possible candidates, - // which by the nature of get_functions happens to be the last candidate. - exprt this_expr=code.arguments()[0]; - assert(this_expr.type().id()==ID_pointer && - "Non-pointer this-arg in remove-virtuals?"); - const auto &points_to=this_expr.type().subtype(); - if(points_to==empty_typet()) - { - symbol_typet symbol_type(functions.back().class_id); - this_expr=typecast_exprt(this_expr, pointer_typet(symbol_type)); - } - exprt deref=dereference_exprt(this_expr, this_expr.type().subtype()); - exprt c_id2=build_class_identifier(deref); + // If necessary, cast to the last candidate function to get the object's clsid. + // By the structure of get_functions, this is the parent of all other classes + // under consideration. + symbol_typet suggested_type(functions.back().class_id); + exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns); goto_programt::targett last_function; for(const auto &fun : functions) From 9e73f42c93f01ab140f80b0bd37b97c0e20ca3cd Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 26 Jan 2017 10:42:24 +0000 Subject: [PATCH 2/2] Remove virtuals style improvements No functional changes intended --- src/goto-programs/class_identifier.cpp | 15 ++++++++------- src/goto-programs/class_identifier.h | 8 ++++---- src/goto-programs/remove_virtual_functions.cpp | 16 +++++++++------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/goto-programs/class_identifier.cpp b/src/goto-programs/class_identifier.cpp index df41fc9c5be..6e814174e51 100644 --- a/src/goto-programs/class_identifier.cpp +++ b/src/goto-programs/class_identifier.cpp @@ -9,6 +9,7 @@ Author: Chris Smowton, chris.smowton@diffblue.com #include "class_identifier.h" #include +#include /*******************************************************************\ @@ -33,25 +34,24 @@ static exprt build_class_identifier( while(1) { const typet &type=ns.follow(e.type()); - assert(type.id()==ID_struct); - const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components=struct_type.components(); assert(!components.empty()); + const auto &first_member_name=components.front().get_name(); member_exprt member_expr( e, - components.front().get_name(), + first_member_name, components.front().type()); - if(components.front().get_name()=="@class_identifier") + if(first_member_name=="@class_identifier") { // found it return member_expr; } else { - e=member_expr; + e.swap(member_expr); } } } @@ -70,7 +70,7 @@ Function: get_class_identifier_field \*******************************************************************/ exprt get_class_identifier_field( - exprt this_expr, + const exprt &this_expr_in, const symbol_typet &suggested_type, const namespacet &ns) { @@ -78,9 +78,10 @@ exprt get_class_identifier_field( // If it's already a pointer to an object of some sort, just use it; // if it's void* then use the suggested type. + exprt this_expr=this_expr_in; assert(this_expr.type().id()==ID_pointer && "Non-pointer this-arg in remove-virtuals?"); - const auto& points_to=this_expr.type().subtype(); + const auto &points_to=this_expr.type().subtype(); if(points_to==empty_typet()) this_expr=typecast_exprt(this_expr, pointer_typet(suggested_type)); exprt deref=dereference_exprt(this_expr, this_expr.type().subtype()); diff --git a/src/goto-programs/class_identifier.h b/src/goto-programs/class_identifier.h index 343a041a547..8ae6dc4ce71 100644 --- a/src/goto-programs/class_identifier.h +++ b/src/goto-programs/class_identifier.h @@ -9,12 +9,12 @@ Author: Chris Smowton, chris.smowton@diffblue.com #ifndef CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H #define CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H -#include -#include -#include +class exprt; +class namespacet; +class symbol_typet; exprt get_class_identifier_field( - exprt this_expr, + const exprt &this_expr, const symbol_typet &suggested_type, const namespacet &ns); diff --git a/src/goto-programs/remove_virtual_functions.cpp b/src/goto-programs/remove_virtual_functions.cpp index 68c388a8cdf..56c89dac3f0 100644 --- a/src/goto-programs/remove_virtual_functions.cpp +++ b/src/goto-programs/remove_virtual_functions.cpp @@ -139,9 +139,9 @@ void remove_virtual_functionst::remove_virtual_function( goto_programt new_code_gotos; exprt this_expr=code.arguments()[0]; - // If necessary, cast to the last candidate function to get the object's clsid. - // By the structure of get_functions, this is the parent of all other classes - // under consideration. + // If necessary, cast to the last candidate function to + // get the object's clsid. By the structure of get_functions, + // this is the parent of all other classes under consideration. symbol_typet suggested_type(functions.back().class_id); exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns); @@ -196,8 +196,10 @@ void remove_virtual_functionst::remove_virtual_function( const irep_idt comment=it->source_location.get_comment(); it->source_location=target->source_location; it->function=target->function; - if(!property_class.empty()) it->source_location.set_property_class(property_class); - if(!comment.empty()) it->source_location.set_comment(comment); + if(!property_class.empty()) + it->source_location.set_property_class(property_class); + if(!comment.empty()) + it->source_location.set_comment(comment); } goto_programt::targett next_target=target; @@ -302,7 +304,8 @@ void remove_virtual_functionst::get_functions( const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; - if(parents.empty()) break; + if(parents.empty()) + break; c=parents.front(); } @@ -380,7 +383,6 @@ bool remove_virtual_functionst::remove_virtual_functions( if(did_something) { - //remove_skip(goto_program); goto_program.update(); }