diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 06f09b1a..ccde0234 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -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(t)) return enum_type_decl_hash()(*d); + if (const typedef_decl* d = dynamic_cast(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; } +// + +/// 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 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 +typedef_decl::get_underlying_type() const +{ + return m_underlying_type; +} + +/// Destructor of the typedef_decl. +typedef_decl::~typedef_decl() +{ +} + +// }//end namespace abigail diff --git a/src/abg-ir.h b/src/abg-ir.h index 2b21c868..517e928e 100644 --- a/src/abg-ir.h +++ b/src/abg-ir.h @@ -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 underlying_type, + location locus); + + bool + operator==(const typedef_decl&) const; + + shared_ptr + get_underlying_type() const; + + virtual ~typedef_decl(); + +private: + shared_ptr 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 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__ diff --git a/src/abg-reader.cc b/src/abg-reader.cc index 9efba147..1d329260 100644 --- a/src/abg-reader.cc +++ b/src/abg-reader.cc @@ -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 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 t(new typedef_decl(name, underlying_type, loc)); + + return ctxt.finish_type_decl_creation(t, id, corpus); +} + }//end namespace reader }//end namespace abigail diff --git a/src/abg-writer.cc b/src/abg-writer.cc index b652bd6d..40c7e61e 100644 --- a/src/abg-writer.cc +++ b/src/abg-writer.cc @@ -152,6 +152,10 @@ static bool write_enum_type_decl(const shared_ptr, const abi_corpus&, write_context&, unsigned); +static bool write_typedef_decl(const shared_ptr, + 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, (decl), corpus, ctxt, indent) || write_enum_type_decl(dynamic_pointer_cast(decl), - corpus, ctxt, indent)) + corpus, ctxt, indent) + || write_typedef_decl(dynamic_pointer_cast(decl), + corpus, ctxt, indent)) return true; return false; @@ -570,5 +576,42 @@ write_enum_type_decl(const shared_ptr 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 decl, + const abi_corpus& corpus, + write_context& ctxt, + unsigned indent) +{ + if (!decl) + return false; + + ostream &o = ctxt.get_ostream(); + + do_indent(o, indent); + + o << ""; + + return true; +} + }//end namespace writer }//end namespace abigail diff --git a/tests/Makefile.am b/tests/Makefile.am index 4d6e64f6..7dfca909 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 diff --git a/tests/data/test-read-write/test7.xml b/tests/data/test-read-write/test7.xml new file mode 100644 index 00000000..9d4214ab --- /dev/null +++ b/tests/data/test-read-write/test7.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/test-read-write.cc b/tests/test-read-write.cc index 87c71170..d2de3179 100644 --- a/tests/test-read-write.cc +++ b/tests/test-read-write.cc @@ -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}