Support typedef declarations

* src/abg-ir.cc (dynamic_type_hash::operator()): Handle hashing of
	a pointer to an instance of typedef_decl.
	(typedef_decl::typedef_decl, typedef_decl::operator==)
	(typedef_decl::operator==, typedef_decl::get_underlying_type)
	(typedef_decl::~typedef_decl): New definitions.
	* src/abg-ir.h (class typedef_decl, struct typedef_decl_hash): New
	declarations.
	* src/abg-reader.cc (handle_typedef_decl): New definition.
	(handle_element): Handle de-serialization of typedef-decl element.
	* src/abg-writer.cc (write_typedef_decl): New definition.
	(write_decl): Handle serialization of an instance of typedef_decl.
	* tests/data/test-read-write/test7.xml: New test.
	* tests/Makefile.am: Add it to the distribution.
	* tests/test-read-write.cc: De-serialize the content of the new
	test, serialize it back and diff both.
This commit is contained in:
Dodji Seketeli 2013-03-30 21:51:43 +01:00
parent 77ade2bde1
commit a5a6fd8fce
7 changed files with 187 additions and 3 deletions

View File

@ -497,6 +497,8 @@ dynamic_type_hash::operator()(const type_base* t) const
return reference_type_def_hash()(*d);
if (const enum_type_decl* d = dynamic_cast<const enum_type_decl*>(t))
return enum_type_decl_hash()(*d);
if (const typedef_decl* d = dynamic_cast<const typedef_decl*>(t))
return typedef_decl_hash()(*d);
// Poor man's fallback case.
return type_base_hash()(*t);
@ -650,4 +652,49 @@ enum_type_decl::operator==(const enum_type_decl& other) const
return true;
}
// <typedef_decl definitions>
/// Constructor of the typedef_decl type.
///
/// \param name the name of the typedef.
///
/// \param underlying_type the underlying type of the typedef.
///
/// \param locus the source location of the typedef declaration.
typedef_decl::typedef_decl(const string& name,
const shared_ptr<type_base> underlying_type,
location locus)
: type_base(underlying_type->get_size_in_bits(),
underlying_type->get_alignment_in_bits()),
decl_base(name, locus),
m_underlying_type(underlying_type)
{
}
/// Equality operator
///
/// \param other the other typedef_decl to test against.
bool
typedef_decl::operator==(const typedef_decl& other) const
{
return (typeid(*this) == typeid(other)
&& get_name() == other.get_name()
&& *get_underlying_type() == *other.get_underlying_type());
}
/// Getter of the underlying type of the typedef.
///
/// \return the underlying_type.
shared_ptr<type_base>
typedef_decl::get_underlying_type() const
{
return m_underlying_type;
}
/// Destructor of the typedef_decl.
typedef_decl::~typedef_decl()
{
}
// </typedef_decl definitions>
}//end namespace abigail

View File

@ -628,5 +628,48 @@ struct enum_type_decl_hash
}
};//end struct enum_type_decl_hash
/// The abstraction of a typedef declaration.
class typedef_decl: public type_base, public decl_base
{
// Forbidden
typedef_decl();
public:
typedef_decl(const string& name,
const shared_ptr<type_base> underlying_type,
location locus);
bool
operator==(const typedef_decl&) const;
shared_ptr<type_base>
get_underlying_type() const;
virtual ~typedef_decl();
private:
shared_ptr<type_base> m_underlying_type;
};//end class typedef_decl
/// Hasher for the typedef_decl type.
struct typedef_decl_hash
{
size_t
operator()(const typedef_decl& t) const
{
hash<string> str_hash;
type_base_hash type_hash;
decl_base_hash decl_hash;
type_shared_ptr_hash type_ptr_hash;
size_t v = str_hash(typeid(t).name());
v = hashing::combine_hashes(v, type_hash(t));
v = hashing::combine_hashes(v, decl_hash(t));
v = hashing::combine_hashes(v, type_ptr_hash(t.get_underlying_type()));
return v;
}
};// end struct typedef_decl_hash
} // end namespace abigail
#endif // __ABG_IR_H__

View File

@ -191,6 +191,7 @@ static bool handle_qualified_type_decl(read_context&, abi_corpus&);
static bool handle_pointer_type_def(read_context&, abi_corpus&);
static bool handle_reference_type_def(read_context&, abi_corpus&);
static bool handle_enum_type_decl(read_context&, abi_corpus&);
static bool handle_typedef_decl(read_context&, abi_corpus&);
bool
read_file(const string& file_path,
@ -328,6 +329,9 @@ handle_element(read_context& ctxt,
if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
BAD_CAST("enum-decl")))
return handle_enum_type_decl(ctxt, corpus);
if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
BAD_CAST("typedef-decl")))
return handle_typedef_decl(ctxt, corpus);
return false;
}
@ -667,5 +671,43 @@ handle_enum_type_decl(read_context& ctxt, abi_corpus& corpus)
return ctxt.finish_type_decl_creation(t, id, corpus);
}
/// Parse a typedef-decl element.
///
/// \param ctxt the context of the parsing.
///
/// \param corpus the corpus the resulting pointer to
/// typedef_decl is added to.
static bool
handle_typedef_decl(read_context& ctxt, abi_corpus& corpus)
{
xml::reader_sptr r = ctxt.get_reader();
if (!r)
return false;
string name;
if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(r, "name"))
name = CHAR_STR(s);
string type_id;
if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(r, "type-id"))
type_id = CHAR_STR(s);
shared_ptr<type_base> underlying_type(ctxt.get_type_decl(type_id));
if (!underlying_type)
return false;
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<type_base> t(new typedef_decl(name, underlying_type, loc));
return ctxt.finish_type_decl_creation(t, id, corpus);
}
}//end namespace reader
}//end namespace abigail

View File

@ -152,6 +152,10 @@ static bool write_enum_type_decl(const shared_ptr<enum_type_decl>,
const abi_corpus&,
write_context&,
unsigned);
static bool write_typedef_decl(const shared_ptr<typedef_decl>,
const abi_corpus&,
write_context&,
unsigned);
static void do_indent(ostream&, unsigned);
/// Emit #nb_whitespaces white spaces into the output stream #o.
@ -241,7 +245,9 @@ write_decl(const shared_ptr<decl_base> decl,
<reference_type_def>(decl),
corpus, ctxt, indent)
|| write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(decl),
corpus, ctxt, indent))
corpus, ctxt, indent)
|| write_typedef_decl(dynamic_pointer_cast<typedef_decl>(decl),
corpus, ctxt, indent))
return true;
return false;
@ -570,5 +576,42 @@ write_enum_type_decl(const shared_ptr<enum_type_decl> decl,
return true;
}
/// Serialize a pointer to an instance of typedef_decl.
///
/// \param decl the typedef_decl 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_typedef_decl(const shared_ptr<typedef_decl> decl,
const abi_corpus& corpus,
write_context& ctxt,
unsigned indent)
{
if (!decl)
return false;
ostream &o = ctxt.get_ostream();
do_indent(o, indent);
o << "<typedef-decl name='" << decl->get_name() << "'";
o << " type-id='" << ctxt.get_id_for_type(decl->get_underlying_type()) << "'";
write_decl_location(decl, corpus, o);
o << " id='"
<< ctxt.get_id_for_type(decl)
<< "'/>";
return true;
}
}//end namespace writer
}//end namespace abigail

View File

@ -26,4 +26,5 @@ $(h)/data/test-read-write/test2.xml \
$(h)/data/test-read-write/test3.xml \
$(h)/data/test-read-write/test4.xml \
$(h)/data/test-read-write/test5.xml \
$(h)/data/test-read-write/test6.xml
$(h)/data/test-read-write/test6.xml \
$(h)/data/test-read-write/test7.xml

View File

@ -0,0 +1,4 @@
<abi-instr version='1.0'>
<type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
<typedef-decl name='tchar' type-id='type-id-1' id='type-id-2'/>
</abi-instr>

View File

@ -48,10 +48,14 @@ InOutSpec in_out_specs[] =
"data/test-read-write/test5.xml",
"output/test-read-write/test5.xml"
},
{
{
"data/test-read-write/test6.xml",
"output/test-read-write/test6.xml"
},
{
"data/test-read-write/test7.xml",
"output/test-read-write/test7.xml"
},
// This should be the last entry.
{NULL, NULL}