Support pointer types & Fix IR types equality

* src/abg-ir.h (location::{operator==, operator<})
	(decl_base::operator==, scope_decl::operator==)
	(type_base::operator==, struct type_shared_ptr_equal)
	(type_decl::operator==, scope_type::operator==)
	(qualified_type_def::operator==, class pointer_type_def): New
	declarations..
	* src/abg-ir.cc (decl_base::operator==, scope_decl::operator==)
	(type_base::operator==, type_decl::operator==)
	(scope_type_decl::operator==, namespace_decl::operator==)
	(qualified_type_def::operator==)
	(pointer_type_def::pointer_type_def, pointer_type_def::operator==)
	(pointer_type_def::get_pointed_to_type)
	(pointer_type_def::~pointer_type_def): New definitions.
	* src/abg-reader.cc (handle_pointer_type_def): New definition.
	(read_input): Handle pointer-type-def
	elements.
	* src/abg-writer.cc (type_shared_ptr_map):  Make this map use the
	use type_shared_ptr_equal predicate.
	(write_pointer_type_def): New definition.
	(write_decl): Improve logic.  Support serializing a pointer to
	pointer_type_def.
	* tests/data/test-read-write/test4.xml: New test input file.
	* tests/Makefile.am: Add tests/data/test-read-write/test4.xml to
	the build system.
	* tests/test-read-write.cc: (De)serialize the new test file.
This commit is contained in:
Dodji Seketeli 2013-03-28 15:27:15 +01:00
parent 57d8b7da41
commit d418d5198f
7 changed files with 377 additions and 23 deletions

View File

@ -4,7 +4,6 @@
#include <iterator>
#include <typeinfo>
#include <tr1/memory>
#include "abg-ir.h"
using std::string;
@ -159,6 +158,20 @@ decl_base::decl_base(const decl_base& d)
m_context = d.m_context;
}
/// Return true iff the two decls have the same name.
///
/// This function doesn't test if the scopes of the the two decls are
/// equal.
bool
decl_base::operator==(const decl_base& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other))
return false;
return get_name() == other.get_name();
}
decl_base::~decl_base()
{
}
@ -184,6 +197,34 @@ scope_decl::scope_decl(location l)
{
}
/// Return true iff both scopes have the same names and have the same
/// member decls.
///
/// This function doesn't check for equality of the scopes of its
/// arguments.
bool
scope_decl::operator==(const scope_decl& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other))
return false;
if (static_cast<decl_base>(*this) != static_cast<decl_base>(other))
return false;
std::list<shared_ptr<decl_base> >::const_iterator i, j;
for (i = get_member_decls().begin(), j = other.get_member_decls().begin();
i != get_member_decls().end() && j != other.get_member_decls().end();
++i, ++j)
if (**i != **j)
return false;
if (i != get_member_decls().end() || j != other.get_member_decls().end())
return false;
return true;
}
/// Add a member decl to this scope. Note that user code should not
/// use this, but rather use #add_decl_to_scope.
///
@ -229,6 +270,20 @@ type_base::type_base(size_t s = 8, size_t a = 8)
{
}
/// Return true iff both type declarations are equal.
///
/// Note that this doesn't test if the scopes of both types are equal.
bool
type_base::operator==(const type_base& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other))
return false;
return (get_size_in_bits() == other.get_size_in_bits()
&& get_alignment_in_bits() == other.get_alignment_in_bits());
}
void
type_base::set_size_in_bits(size_t s)
{
@ -270,6 +325,20 @@ type_decl::type_decl(const std::string& name,
{
}
/// Return true if both types equals.
///
/// Note that this does not check the scopes of any of the types.
bool
type_decl::operator==(const type_decl& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other))
return false;
return (static_cast<decl_base>(*this) == other
&& static_cast<type_base>(*this) == other);
}
type_decl::~type_decl()
{
}
@ -287,6 +356,21 @@ scope_type_decl::scope_type_decl(const std::string& name,
{
}
/// Return true iff both scope types are equal.
///
/// Note that this function does not consider the scope of the scope
/// types themselves.
bool
scope_type_decl::operator==(const scope_type_decl& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other))
return false;
return (static_cast<scope_decl>(*this) == other
&& static_cast<type_base>(*this) == other);
}
scope_type_decl::~scope_type_decl()
{
}
@ -300,6 +384,20 @@ namespace_decl::namespace_decl(const std::string& name,
{
}
/// Return true iff both namespaces and their members are equal.
///
/// Note that this function does not check if the scope of these
/// namespaces are equal.
bool
namespace_decl::operator==(const namespace_decl& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other))
return false;
return (static_cast<scope_decl>(*this) == other);
}
namespace_decl::~namespace_decl()
{
}
@ -331,6 +429,24 @@ qualified_type_def::qualified_type_def(shared_ptr<type_base> type,
set_name(get_name() + dynamic_pointer_cast<decl_base>(type)->get_name());
}
/// Return true iff both qualified types are equal.
///
/// Note that this function does not check for equality of the scopes.
bool
qualified_type_def::operator==(const qualified_type_def& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other)
|| get_cv_quals() != other.get_cv_quals()
|| get_underlying_type() != other.get_underlying_type())
return false;
if (shared_ptr<type_base> u = get_underlying_type())
return (*u == *other.get_underlying_type());
return true;
}
/// The destructor of the qualified type
qualified_type_def::~qualified_type_def()
{
@ -383,4 +499,43 @@ dynamic_type_hash::operator()(const type_base* t) const
// Poor man's fallback case.
return type_base_hash()(*t);
}
pointer_type_def::pointer_type_def(shared_ptr<type_base>& pointed_to,
size_t size_in_bits,
size_t align_in_bits,
location locus)
: type_base(size_in_bits, align_in_bits),
decl_base("", locus),
m_pointed_to_type(pointed_to)
{
}
/// Return true iff both instances of pointer_type_def are equal.
///
/// Note that this function does not check for the scopes of the this
/// types.
bool
pointer_type_def::operator==(const pointer_type_def& other) const
{
// Runtime types must be equal.
if (typeid(*this) != typeid(other)
|| get_pointed_to_type() != other.get_pointed_to_type())
return false;
if (shared_ptr<type_base> c = get_pointed_to_type())
return *c == *other.get_pointed_to_type();
return true;
}
shared_ptr<type_base>
pointer_type_def::get_pointed_to_type() const
{
return m_pointed_to_type;
}
pointer_type_def::~pointer_type_def()
{
}
}//end namespace abigail

View File

@ -9,7 +9,7 @@
#include <string>
#include <tr1/functional>
#include <typeinfo>
#include <utility> // for std::rel_ops, at least.
#include "abg-hash.h"
using std::tr1::shared_ptr;
@ -19,6 +19,10 @@ using std::string;
// Our real stuff
namespace abigail
{
using namespace std::rel_ops; // Pull in relational operators so that
// we don't have to define them all here.
/// \brief The source location of a token.
///
/// This represents the location of a token coming from a given ABI
@ -50,6 +54,14 @@ public:
return !!m_value;
}
bool
operator==(const location other) const
{return m_value == other.m_value;}
bool
operator<(const location other) const
{return m_value < other.m_value;}
friend class location_manager;
private:
@ -99,8 +111,14 @@ public:
decl_base(const std::string& name,
location locus);
decl_base(location);
decl_base(const decl_base&);
virtual bool
operator==(const decl_base&) const;
virtual ~decl_base();
location
@ -153,8 +171,12 @@ class scope_decl : public decl_base
public:
scope_decl(const std::string& name,
location locus);
scope_decl(location);
virtual bool
operator==(const scope_decl&) const;
const std::list<shared_ptr<decl_base> >&
get_member_decls() const;
@ -198,6 +220,10 @@ class type_base
public:
type_base(size_t s, size_t a);
virtual bool
operator==(const type_base&) const;
virtual ~type_base();
void
@ -253,6 +279,24 @@ struct type_shared_ptr_hash
}
};//end struct type_shared_ptr_hash
/// A predicate for deep equality of instances of
/// shared_ptr<type_base>
struct type_shared_ptr_equal
{
bool
operator()(const shared_ptr<type_base>l,
const shared_ptr<type_base>r) const
{
if (l != r)
return false;
if (l)
return *l == *r;
return true;
}
};//end struct type_shared_ptr_equal
/// A basic type declaration that introduces no scope.
class type_decl : public decl_base, public type_base
{
@ -266,6 +310,9 @@ public:
size_t alignment_in_bits,
location locus);
virtual bool
operator==(const type_decl&) const;
virtual ~type_decl();
};// class type_decl
@ -297,6 +344,9 @@ public:
size_t alignment_in_bits,
location locus);
virtual bool
operator==(const scope_type_decl&) const;
virtual ~scope_type_decl();
};
@ -324,6 +374,9 @@ public:
namespace_decl(const std::string& name,
location locus);
virtual bool
operator==(const namespace_decl&) const;
virtual ~namespace_decl();
};//end class namespace_decl
@ -331,6 +384,8 @@ public:
class qualified_type_def : public type_base, public decl_base
{
// Forbidden.
qualified_type_def();
public:
/// Bit field values representing the cv qualifiers of the
/// underlying type.
@ -345,6 +400,9 @@ public:
CV quals,
location locus);
virtual bool
operator==(const qualified_type_def&) const;
char
get_cv_quals() const;
@ -378,5 +436,30 @@ struct qualified_type_def_hash
}
};//end struct qualified_type_def_hash
/// The abstraction of a pointer type.
class pointer_type_def : public type_base, public decl_base
{
// Forbidden.
pointer_type_def();
public:
pointer_type_def(shared_ptr<type_base>& pointed_to_type,
size_t size_in_bits,
size_t alignment_in_bits,
location locus);
virtual bool
operator==(const pointer_type_def&) const;
shared_ptr<type_base>
get_pointed_to_type() const;
virtual ~pointer_type_def();
private:
shared_ptr<type_base> m_pointed_to_type;
};//end class pointer_type_def
} // end namespace abigail
#endif // __ABL_IR_H__

View File

@ -140,14 +140,15 @@ private:
stack<shared_ptr<decl_base> > m_decls_stack;
};//end class read_context
static void update_read_context(read_context&);
static int advance_cursor(read_context&);
static bool read_input(read_context&, abi_corpus&);
static bool read_location(read_context&, abi_corpus& , location&);
static bool handle_element(read_context&, abi_corpus&);
static bool handle_type_decl(read_context&, abi_corpus&);
static bool handle_namespace_decl(read_context&, abi_corpus&);
static bool handle_qualified_type_decl(read_context&, abi_corpus&);
static void update_read_context(read_context&);
static int advance_cursor(read_context&);
static bool read_input(read_context&, abi_corpus&);
static bool read_location(read_context&, abi_corpus& , location&);
static bool handle_element(read_context&, abi_corpus&);
static bool handle_type_decl(read_context&, abi_corpus&);
static bool handle_namespace_decl(read_context&, abi_corpus&);
static bool handle_qualified_type_decl(read_context&, abi_corpus&);
static bool handle_pointer_type_def(read_context&, abi_corpus&);
bool
read_file(const string& file_path,
@ -212,7 +213,7 @@ advance_cursor(read_context& ctxt)
///
/// \param corpus the result of the parsing.
///
/// \return true upon successufl parsing, false otherwise.
/// \return true upon successful parsing, false otherwise.
static bool
read_input(read_context& ctxt,
abi_corpus& corpus)
@ -276,6 +277,9 @@ handle_element(read_context& ctxt,
if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
BAD_CAST("qualified-type-def")))
return handle_qualified_type_decl(ctxt, corpus);
if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
BAD_CAST("pointer-type-def")))
return handle_pointer_type_def(ctxt, corpus);
return false;
}
@ -411,7 +415,7 @@ handle_namespace_decl(read_context& ctxt, abi_corpus& corpus)
return true;
}
/// Parse qualified-type-def xml element
/// Parse a qualified-type-def xml element.
///
/// \param ctxt the parsing context.
///
@ -480,5 +484,61 @@ handle_qualified_type_decl(read_context& ctxt, abi_corpus& corpus)
return true;
}
/// Parse a pointer-type-decl element.
///
/// \param ctxt the context of the parsing.
///
/// \param corpus the ABI Corpus to augment with the result of the
/// parsing.
///
/// \return true upon successful completion, false otherwise.
static bool
handle_pointer_type_def(read_context& ctxt, abi_corpus& corpus)
{
xml::reader_sptr r = ctxt.get_reader();
if (!r)
return false;
string type_id;
if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(r, "type-id"))
type_id = CHAR_STR(s);
shared_ptr<type_base> pointed_to_type = ctxt.get_type_decl(type_id);
if (!pointed_to_type)
return false;
size_t size_in_bits = 0, alignment_in_bits = 0;
if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(r, "size-in-bits"))
size_in_bits = atoi(CHAR_STR(s));
if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(r, "alignment-in-bits"))
alignment_in_bits = atoi(CHAR_STR(s));
string id;
if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(r, "id"))
id = CHAR_STR(s);
if (id.empty() || ctxt.get_type_decl(id))
return false;
location loc;
read_location(ctxt, corpus, loc);
shared_ptr<decl_base> decl =
shared_ptr<decl_base> (new pointer_type_def(pointed_to_type,
size_in_bits,
alignment_in_bits,
loc));
add_decl_to_scope(decl, ctxt.get_cur_scope());
if (!decl->get_scope())
corpus.add(decl);
ctxt.push_decl(decl);
ctxt.add_type_decl(id, dynamic_pointer_cast<type_base>(decl));
return true;
}
}//end namespace reader
}//end namespace abigail

View File

@ -9,6 +9,7 @@
using std::tr1::shared_ptr;
using std::tr1::dynamic_pointer_cast;
using std::tr1::static_pointer_cast;
using std::ostream;
using std::ostringstream;
using std::list;
@ -61,7 +62,8 @@ private:
typedef unordered_map<shared_ptr<type_base>,
string,
type_shared_ptr_hash> type_shared_ptr_map;
type_shared_ptr_hash,
type_shared_ptr_equal> type_shared_ptr_map;
class write_context
{
write_context();
@ -138,7 +140,11 @@ static bool write_qualified_type_def(const shared_ptr<qualified_type_def>,
const abi_corpus&,
write_context&,
unsigned);
void do_indent(ostream&, unsigned);
static bool write_pointer_type_def(const shared_ptr<pointer_type_def>,
const abi_corpus&,
write_context&,
unsigned);
static void do_indent(ostream&, unsigned);
/// Emit #nb_whitespaces white spaces into the output stream #o.
void
@ -215,13 +221,14 @@ write_decl(const shared_ptr<decl_base> decl,
unsigned indent)
{
if (write_type_decl(dynamic_pointer_cast<type_decl> (decl),
corpus, ctxt, indent))
return true;
if (write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl),
corpus, ctxt, indent))
return true;
if (write_qualified_type_def(dynamic_pointer_cast<qualified_type_def>(decl),
corpus, ctxt, indent))
corpus, ctxt, indent)
|| write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl),
corpus, ctxt, indent)
|| write_qualified_type_def (dynamic_pointer_cast<qualified_type_def>
(decl),
corpus, ctxt, indent)
|| write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(decl),
corpus, ctxt, indent))
return true;
return false;
@ -400,7 +407,7 @@ write_qualified_type_def(const shared_ptr<qualified_type_def> decl,
if (decl->get_cv_quals() & qualified_type_def::CV_VOLATILE)
o << " volatile='yes'";
write_decl_location(dynamic_pointer_cast<decl_base>(decl), corpus, o);
write_decl_location(static_pointer_cast<decl_base>(decl), corpus, o);
o<< " id='"
<< ctxt.get_id_for_type(decl)
@ -411,5 +418,45 @@ write_qualified_type_def(const shared_ptr<qualified_type_def> decl,
return true;
}
/// Serialize a pointer to an instance of pointer_type_def.
///
/// \param decl the pointer_type_def to serialize.
///
/// \param corpus the ABI corpus it belongs to.
///
/// \param ctxt the context of the serialization.
///
/// \param indent the number of indentation white spaces to use.
///
/// \return true upon succesful completion, false otherwise.
static bool
write_pointer_type_def(const shared_ptr<pointer_type_def> decl,
const abi_corpus& corpus,
write_context& ctxt,
unsigned indent)
{
if (!decl)
return false;
ostream &o = ctxt.get_ostream();
do_indent(o, indent);
o << "<pointer-type-def type-id='"
<< ctxt.get_id_for_type(decl->get_pointed_to_type())
<< "'";
if (size_t s = decl->get_size_in_bits())
o << " size-in-bits='" << s << "'";
if (size_t s = decl->get_alignment_in_bits())
o << " alignment-in-bits='" << s << "'";
o << " id='" << ctxt.get_id_for_type(decl) << "'";
write_decl_location(static_pointer_cast<decl_base>(decl), corpus, o);
o << "/>";
return true;
}
}//end namespace writer
}//end namespace abigail

View File

@ -23,4 +23,5 @@ EXTRA_DIST= \
$(h)/data/test-read-write/test0.xml \
$(h)/data/test-read-write/test1.xml \
$(h)/data/test-read-write/test2.xml \
$(h)/data/test-read-write/test3.xml
$(h)/data/test-read-write/test3.xml \
$(h)/data/test-read-write/test4.xml

View File

@ -0,0 +1,4 @@
<abi-instr version='1.0'>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
<pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
</abi-instr>

View File

@ -40,6 +40,10 @@ InOutSpec in_out_specs[] =
"data/test-read-write/test3.xml",
"output/test-read-write/test3.xml"
},
{
"data/test-read-write/test4.xml",
"output/test-read-write/test4.xml"
},
// This should be the last entry.
{NULL, NULL}