mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-14 22:14:35 +00:00
Initial support of class templates
* src/abg-ir.cc (class_template_decl::class_template_decl) (class_template_decl::set_pattern) (class_template_decl::operator==) (class_template_decl::~class_template_decl) (class_template_decl_hash::operator()) (class_tmpl_shared_ptr_hash::operator()): New definitions. * src/abg-ir.h (class class_template_decl, struct class_tmpl_shared_ptr_hash, struct class_tmpl_shared_ptr_hash): New declarations. * src/abg-reader.cc (read_context::const_class_tmpl_map_it): New typedef. (read_context::get_fn_tmpl_decl): Fix comment. (read_context::{get_class_tmpl_decl,key_class_tmpl_decl}) (build_class_template_decl, handle_class_template_decl): New definitions. (read_context::m_class_tmpl_map): New member. (handle_element): Support "class-template-decl" xml elements nodes. (build_class_decl): Add missing bits to comment. (build_function_template_decl): Fix spacing. * src/abg-writer.cc (class_tmpl_shared_ptr_map): New typedef. (write_context::m_class_tmpl_map): New member. (write_context::get_id_for_class_tmpl, write_class_template_decl): New definitions. (write_template_parameters): Factorize this this out from ... (write_function_template_decl): ... here. (write_decl): Support writing instances of class_template_decl. Fix spacing. * tests/data/test-read-write/test15.xml: New test input. * tests/Makefile.am: Add the new test15.xml input to the distribution. * tests/test-read-write.cc (in_out_specs): Add the new test15.xml test to the list of serialized output to be de-serialized and serialized back.
This commit is contained in:
parent
9b14a86ac4
commit
c50b9dbb55
@ -1680,4 +1680,66 @@ function_template_decl::~function_template_decl()
|
||||
{
|
||||
}
|
||||
// </function_template>
|
||||
|
||||
// <class template>
|
||||
class_template_decl::class_template_decl(shared_ptr<class_decl> pattern,
|
||||
location locus,
|
||||
visibility vis)
|
||||
: decl_base(pattern->get_name(), locus,
|
||||
pattern->get_name(), vis),
|
||||
scope_decl(pattern->get_name(), locus)
|
||||
{set_pattern(pattern);}
|
||||
|
||||
void
|
||||
class_template_decl::set_pattern(shared_ptr<class_decl> p)
|
||||
{
|
||||
m_pattern = p;
|
||||
add_decl_to_scope(p, this);
|
||||
set_name(p->get_name());
|
||||
}
|
||||
|
||||
bool
|
||||
class_template_decl::operator==(const class_template_decl& o) const
|
||||
{
|
||||
if (!(static_cast<template_decl>(*this) == o
|
||||
&& static_cast<scope_decl>(*this) == o
|
||||
&& !!get_pattern() == !!o.get_pattern()))
|
||||
return false;
|
||||
|
||||
return (*get_pattern() == *o.get_pattern());
|
||||
}
|
||||
|
||||
class_template_decl::~class_template_decl()
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
class_template_decl_hash::operator()(const class_template_decl& t) const
|
||||
{
|
||||
hash<string> hash_string;
|
||||
decl_base_hash hash_decl_base;
|
||||
template_decl_hash hash_template_decl;
|
||||
class_decl_hash hash_class_decl;
|
||||
|
||||
size_t v = hash_string(typeid(t).name());
|
||||
v = hashing::combine_hashes(v, hash_decl_base(t));
|
||||
v = hashing::combine_hashes(v, hash_template_decl(t));
|
||||
if (t.get_pattern())
|
||||
v = hashing::combine_hashes(v, hash_class_decl(*t.get_pattern()));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t
|
||||
class_tmpl_shared_ptr_hash::operator()
|
||||
(const shared_ptr<class_template_decl> t) const
|
||||
{
|
||||
class_template_decl_hash hash_class_tmpl_decl;
|
||||
|
||||
if (t)
|
||||
return hash_class_tmpl_decl(*t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// </class template>
|
||||
}//end namespace abigail
|
||||
|
67
src/abg-ir.h
67
src/abg-ir.h
@ -51,6 +51,7 @@ using namespace std::rel_ops; // Pull in relational operators so that
|
||||
class decl_base;
|
||||
class scope_decl;
|
||||
class global_scope;
|
||||
class class_decl;
|
||||
class translation_unit;
|
||||
|
||||
void add_decl_to_scope(shared_ptr<decl_base>,
|
||||
@ -1166,18 +1167,76 @@ private:
|
||||
binding m_binding;
|
||||
};//end class function_template_decl
|
||||
|
||||
/// Hash functor for
|
||||
/// Hashing functor for pointer to a function template.
|
||||
struct fn_tmpl_shared_ptr_hash
|
||||
{
|
||||
size_t
|
||||
operator()(const shared_ptr<function_template_decl>) const;
|
||||
};//end struct fn_tmpl_shared_ptr_hash
|
||||
|
||||
/// Hash functor for function templates
|
||||
struct function_template_decl_hash
|
||||
{
|
||||
size_t
|
||||
operator()(const function_template_decl&) const;
|
||||
};// end struct function_template_decl_hash
|
||||
|
||||
struct fn_tmpl_shared_ptr_hash
|
||||
/// Abstract a class template.
|
||||
class class_template_decl : public template_decl, public scope_decl
|
||||
{
|
||||
// Forbidden
|
||||
class_template_decl();
|
||||
|
||||
public:
|
||||
class_template_decl(location locus,
|
||||
visibility vis = VISIBILITY_DEFAULT)
|
||||
: decl_base("", locus, "", vis),
|
||||
scope_decl("", locus)
|
||||
{}
|
||||
|
||||
/// Constructor for the class_template_decl type.
|
||||
///
|
||||
/// \param the pattern of the class template. This must NOT be a
|
||||
/// null pointer. If you really this to be null, please use the
|
||||
/// constructor above instead.
|
||||
///
|
||||
/// \param the source location of the declaration of the type.
|
||||
///
|
||||
/// \param the visibility of the instances of class instantiated
|
||||
/// from this template.
|
||||
class_template_decl(shared_ptr<class_decl> pattern,
|
||||
location locus,
|
||||
visibility vis = VISIBILITY_DEFAULT);
|
||||
|
||||
|
||||
virtual bool
|
||||
operator==(const class_template_decl&) const;
|
||||
|
||||
void
|
||||
set_pattern(shared_ptr<class_decl> p);
|
||||
|
||||
shared_ptr<class_decl>
|
||||
get_pattern() const
|
||||
{return m_pattern;}
|
||||
|
||||
|
||||
virtual ~class_template_decl();
|
||||
|
||||
private:
|
||||
shared_ptr<class_decl> m_pattern;
|
||||
};// end class class_template_decl
|
||||
|
||||
struct class_template_decl_hash
|
||||
{
|
||||
size_t
|
||||
operator()(const shared_ptr<function_template_decl>) const;
|
||||
};//end struct fn_tmpl_shared_ptr_hash
|
||||
operator()(const class_template_decl&) const;
|
||||
};// end struct class_template_decl_hash
|
||||
|
||||
struct class_tmpl_shared_ptr_hash
|
||||
{
|
||||
size_t
|
||||
operator()(const shared_ptr<class_template_decl>) const;
|
||||
};// end struct class_tmpl_shared_ptr_hash
|
||||
|
||||
/// Abstracts a class declaration.
|
||||
class class_decl : public scope_type_decl
|
||||
|
@ -73,6 +73,10 @@ public:
|
||||
shared_ptr<function_template_decl> >::const_iterator
|
||||
const_fn_tmpl_map_it;
|
||||
|
||||
typedef unordered_map<string,
|
||||
shared_ptr<class_template_decl> >::const_iterator
|
||||
const_class_tmpl_map_it;
|
||||
|
||||
read_context(xml::reader_sptr reader)
|
||||
: m_depth(0),
|
||||
m_reader(reader)
|
||||
@ -115,9 +119,10 @@ public:
|
||||
}
|
||||
|
||||
/// Return the function template that is identified by a unique ID.
|
||||
/// Note that a function template to be indentified by #id, the
|
||||
/// function key_fn_tmpl_decl must have been previously called
|
||||
/// with that function template and with #id.
|
||||
///
|
||||
/// Note that for a function template to be identified by #id, the
|
||||
/// function key_fn_tmpl_decl must have been previously called with
|
||||
/// that function template and with #id.
|
||||
///
|
||||
/// \param id the ID to consider.
|
||||
///
|
||||
@ -133,6 +138,25 @@ public:
|
||||
return i->second;
|
||||
}
|
||||
|
||||
/// Return the class template that is identified by a unique ID.
|
||||
///
|
||||
/// Note that for a class template to be identified by #id, the
|
||||
/// function key_class_tmpl_decl must have been previously called
|
||||
/// with that class template and with #id.
|
||||
///
|
||||
/// \param id the ID to consider.
|
||||
///
|
||||
/// \return the class template identified by #id, or a null pointer
|
||||
/// if no class template has ever been associated with #id before.
|
||||
shared_ptr<class_template_decl>
|
||||
get_class_tmpl_decl(const string& id) const
|
||||
{
|
||||
const_class_tmpl_map_it i = m_class_tmpl_map.find(id);
|
||||
if (i == m_class_tmpl_map.end())
|
||||
return shared_ptr<class_template_decl>();
|
||||
return i->second;
|
||||
}
|
||||
|
||||
/// Return the current lexical scope. For this function to return a
|
||||
/// sane result, the path to the current decl element (starting from the
|
||||
/// root element) must be up to date. It is updated by a call to
|
||||
@ -239,6 +263,29 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Associate an ID to a class template.
|
||||
///
|
||||
/// \param class_tmpl_decl the class template to consider.
|
||||
///
|
||||
/// \param id the ID to associate to the class template.
|
||||
///
|
||||
/// \return true upon successful completion, false otherwise. Note
|
||||
/// that the function returns false if an ID was previously
|
||||
/// associated to the class template.
|
||||
bool
|
||||
key_class_tmpl_decl(shared_ptr<class_template_decl> class_tmpl_decl,
|
||||
const string& id)
|
||||
{
|
||||
assert(class_tmpl_decl);
|
||||
|
||||
const_class_tmpl_map_it i = m_class_tmpl_map.find(id);
|
||||
if (i != m_class_tmpl_map.end())
|
||||
return false;
|
||||
|
||||
m_class_tmpl_map[id] = class_tmpl_decl;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// This function must be called on each decl that is created during
|
||||
/// the parsing. It adds the decl to the current scope, and updates
|
||||
/// the state of the parsing context accordingly.
|
||||
@ -335,6 +382,7 @@ private:
|
||||
int m_depth;
|
||||
unordered_map<string, shared_ptr<type_base> > m_types_map;
|
||||
unordered_map<string, shared_ptr<function_template_decl> > m_fn_tmpl_map;
|
||||
unordered_map<string, shared_ptr<class_template_decl> > m_class_tmpl_map;
|
||||
xml::reader_sptr m_reader;
|
||||
stack<shared_ptr<decl_base> > m_decls_stack;
|
||||
};//end class read_context
|
||||
@ -380,6 +428,8 @@ static shared_ptr<class_decl>
|
||||
build_class_decl(read_context&, const xmlNodePtr, bool);
|
||||
static shared_ptr<function_template_decl>
|
||||
build_function_template_decl(read_context&, const xmlNodePtr, bool);
|
||||
static shared_ptr<class_template_decl>
|
||||
build_class_template_decl(read_context&, const xmlNodePtr, bool);
|
||||
static shared_ptr<template_type_parameter>
|
||||
build_template_type_parameter(read_context&, const xmlNodePtr, unsigned, bool);
|
||||
static shared_ptr<tmpl_parm_type_composition>
|
||||
@ -416,6 +466,8 @@ static bool handle_var_decl(read_context&);
|
||||
static bool handle_function_decl(read_context&);
|
||||
static bool handle_class_decl(read_context&);
|
||||
static bool handle_function_template_decl(read_context&);
|
||||
static bool handle_class_template_decl(read_context&);
|
||||
|
||||
bool
|
||||
read_file(const string& file_path,
|
||||
translation_unit& tu)
|
||||
@ -619,6 +671,9 @@ handle_element(read_context& ctxt)
|
||||
if (xmlStrEqual(XML_READER_GET_NODE_NAME(reader).get(),
|
||||
BAD_CAST("function-template-decl")))
|
||||
return handle_function_template_decl(ctxt);
|
||||
if (xmlStrEqual(XML_READER_GET_NODE_NAME(reader).get(),
|
||||
BAD_CAST("class-template-decl")))
|
||||
return handle_class_template_decl(ctxt);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1487,6 +1542,9 @@ build_typedef_decl(read_context& ctxt,
|
||||
///
|
||||
/// \param node the xml node to build the class_decl from.
|
||||
///
|
||||
/// \param update_depth_info whether to update the depth info carried
|
||||
/// by the parsing context.
|
||||
///
|
||||
/// \return a pointer to class_decl upon successful completion, a null
|
||||
/// pointer otherwise.
|
||||
static shared_ptr<class_decl>
|
||||
@ -1727,7 +1785,7 @@ build_function_template_decl(read_context& ctxt,
|
||||
ctxt.push_decl_to_current_scope(fn_tmpl_decl, node, update_depth_info);
|
||||
|
||||
unsigned parm_index = 0;
|
||||
for (xmlNodePtr n = node->children; n ; n = n->next)
|
||||
for (xmlNodePtr n = node->children; n; n = n->next)
|
||||
{
|
||||
if (n->type != XML_ELEMENT_NODE)
|
||||
continue;
|
||||
@ -1749,6 +1807,75 @@ build_function_template_decl(read_context& ctxt,
|
||||
return fn_tmpl_decl;
|
||||
}
|
||||
|
||||
/// Build an intance of #class_template_decl, from a
|
||||
/// 'class-template-decl' xml element node.
|
||||
///
|
||||
/// \param ctxt the context of the parsing.
|
||||
///
|
||||
/// \param node the xml node to parse from.
|
||||
///
|
||||
/// \param update_depth_info this must be set to false, if we reached
|
||||
/// this xml node by calling the xmlTextReaderRead function. In that
|
||||
/// case, build_class_decl doesn't have to update the depth
|
||||
/// information that is maintained in the context of the parsing.
|
||||
/// Otherwise if this node if just a child grand child of a node that
|
||||
/// we reached using xmlTextReaderRead, of if it wasn't reached via
|
||||
/// xmlTextReaderRead at all,then the argument to this parameter
|
||||
/// should be true. In that case this function will update the depth
|
||||
/// information that is maintained by in the context of the parsing.
|
||||
///
|
||||
/// \return the newly built function_template_decl upon successful
|
||||
/// completion, a null pointer otherwise.
|
||||
static shared_ptr<class_template_decl>
|
||||
build_class_template_decl(read_context& ctxt,
|
||||
const xmlNodePtr node,
|
||||
bool update_depth_info)
|
||||
{
|
||||
shared_ptr<class_template_decl> nil, result;
|
||||
|
||||
if (!xmlStrEqual(node->name, BAD_CAST("class-template-decl")))
|
||||
return nil;
|
||||
|
||||
string id;
|
||||
if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
|
||||
id = CHAR_STR(s);
|
||||
if (id.empty() || ctxt.get_class_tmpl_decl(id))
|
||||
return nil;
|
||||
|
||||
location loc;
|
||||
read_location(ctxt, node, loc);
|
||||
|
||||
decl_base::visibility vis = decl_base::VISIBILITY_NONE;
|
||||
read_visibility(node, vis);
|
||||
|
||||
shared_ptr<class_template_decl> class_tmpl
|
||||
(new class_template_decl(loc, vis));
|
||||
|
||||
ctxt.push_decl_to_current_scope(class_tmpl, node, update_depth_info);
|
||||
|
||||
unsigned parm_index = 0;
|
||||
for (xmlNodePtr n = node->children; n; n = n->next)
|
||||
{
|
||||
if (n->type != XML_ELEMENT_NODE)
|
||||
continue;
|
||||
|
||||
if (shared_ptr<template_parameter> parm=
|
||||
build_template_parameter(ctxt, n, parm_index,
|
||||
/*update_depth_info=*/true))
|
||||
{
|
||||
class_tmpl->add_template_parameter(parm);
|
||||
++parm_index;
|
||||
}
|
||||
else if (shared_ptr<class_decl> c =
|
||||
build_class_decl(ctxt, n, /*update_depth_info=*/true))
|
||||
class_tmpl->set_pattern(c);
|
||||
}
|
||||
|
||||
ctxt.key_class_tmpl_decl(class_tmpl, id);
|
||||
|
||||
return class_tmpl;
|
||||
}
|
||||
|
||||
/// Build a template_type_parameter from a 'template-type-parameter'
|
||||
/// xml element node.
|
||||
///
|
||||
@ -2514,5 +2641,28 @@ handle_function_template_decl(read_context& ctxt)
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
/// Parse a 'class-template-decl' xml element.
|
||||
///
|
||||
/// \param ctxt the context of the parsing.
|
||||
///
|
||||
/// \return true upon successful completion, false otherwise.
|
||||
static bool
|
||||
handle_class_template_decl(read_context& ctxt)
|
||||
{
|
||||
xml::reader_sptr r = ctxt.get_reader();
|
||||
if (!r)
|
||||
return false;
|
||||
|
||||
xmlNodePtr node = xmlTextReaderExpand(r.get());
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
bool is_ok = build_class_template_decl(ctxt, node,
|
||||
/*update_depth_info=*/false);
|
||||
xmlTextReaderNext(r.get());
|
||||
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
}//end namespace reader
|
||||
}//end namespace abigail
|
||||
|
@ -92,6 +92,11 @@ typedef unordered_map<shared_ptr<type_base>,
|
||||
typedef unordered_map<shared_ptr<function_template_decl>,
|
||||
string,
|
||||
fn_tmpl_shared_ptr_hash> fn_tmpl_shared_ptr_map;
|
||||
|
||||
typedef unordered_map<shared_ptr<class_template_decl>,
|
||||
string,
|
||||
class_tmpl_shared_ptr_hash> class_tmpl_shared_ptr_map;
|
||||
|
||||
class write_context
|
||||
{
|
||||
write_context();
|
||||
@ -156,12 +161,26 @@ public:
|
||||
return m_fn_tmpl_id_map[f];
|
||||
}
|
||||
|
||||
string
|
||||
get_id_for_class_tmpl(shared_ptr<class_template_decl> c)
|
||||
{
|
||||
class_tmpl_shared_ptr_map::const_iterator it = m_class_tmpl_id_map.find(c);
|
||||
if (it == m_class_tmpl_id_map.end())
|
||||
{
|
||||
string id = get_id_manager().get_id_with_prefix("class-tmpl-id-");
|
||||
m_class_tmpl_id_map[c] = id;
|
||||
return id;
|
||||
}
|
||||
return m_class_tmpl_id_map[c];
|
||||
}
|
||||
|
||||
private:
|
||||
id_manager m_id_manager;
|
||||
config m_config;
|
||||
ostream& m_ostream;
|
||||
type_shared_ptr_map m_type_id_map;
|
||||
fn_tmpl_shared_ptr_map m_fn_tmpl_id_map;
|
||||
class_tmpl_shared_ptr_map m_class_tmpl_id_map;
|
||||
};//end write_context
|
||||
|
||||
static bool write_translation_unit(const translation_unit&,
|
||||
@ -207,9 +226,14 @@ static bool write_tmpl_parm_type_composition
|
||||
(const shared_ptr<tmpl_parm_type_composition>, write_context&, unsigned);
|
||||
static bool write_template_parameter(const shared_ptr<template_parameter>,
|
||||
write_context&, unsigned);
|
||||
static void write_template_parameters(const shared_ptr<template_decl>,
|
||||
write_context&, unsigned);
|
||||
static bool write_function_template_decl
|
||||
(const shared_ptr<function_template_decl>,
|
||||
write_context&, unsigned);
|
||||
static bool write_class_template_decl
|
||||
(const shared_ptr<class_template_decl>,
|
||||
write_context&, unsigned);
|
||||
static void do_indent(ostream&, unsigned);
|
||||
static void do_indent_to_level(write_context&, unsigned, unsigned);
|
||||
static unsigned get_indent_to_level(write_context&, unsigned, unsigned);
|
||||
@ -532,21 +556,19 @@ write_decl(const shared_ptr<decl_base> decl,
|
||||
|| write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(decl),
|
||||
ctxt, indent)
|
||||
|| write_reference_type_def(dynamic_pointer_cast
|
||||
<reference_type_def>(decl),
|
||||
ctxt, indent)
|
||||
<reference_type_def>(decl), ctxt, indent)
|
||||
|| write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(decl),
|
||||
ctxt, indent)
|
||||
|| write_typedef_decl(dynamic_pointer_cast<typedef_decl>(decl),
|
||||
ctxt, indent)
|
||||
|| write_var_decl(dynamic_pointer_cast<var_decl>(decl),
|
||||
ctxt, indent)
|
||||
|| write_var_decl(dynamic_pointer_cast<var_decl>(decl), ctxt, indent)
|
||||
|| write_function_decl(dynamic_pointer_cast<function_decl>(decl),
|
||||
ctxt, indent)
|
||||
|| write_class_decl(dynamic_pointer_cast<class_decl>(decl),
|
||||
ctxt, indent)
|
||||
|| write_class_decl(dynamic_pointer_cast<class_decl>(decl), ctxt, indent)
|
||||
|| (write_function_template_decl
|
||||
(dynamic_pointer_cast<function_template_decl>(decl),
|
||||
ctxt, indent)))
|
||||
(dynamic_pointer_cast<function_template_decl>(decl), ctxt, indent))
|
||||
|| (write_class_template_decl
|
||||
(dynamic_pointer_cast<class_template_decl>(decl), ctxt, indent)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -1305,6 +1327,29 @@ write_template_parameter(const shared_ptr<template_parameter> decl,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Serialize the template parameters of the a given template.
|
||||
///
|
||||
/// \param tmpl the template for which to emit the template parameters.
|
||||
static void
|
||||
write_template_parameters(const shared_ptr<template_decl> tmpl,
|
||||
write_context& ctxt, unsigned indent)
|
||||
{
|
||||
if (!tmpl)
|
||||
return;
|
||||
|
||||
ostream &o = ctxt.get_ostream();
|
||||
|
||||
unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
|
||||
for (list<shared_ptr<template_parameter> >::const_iterator p =
|
||||
tmpl->get_template_parameters().begin();
|
||||
p != tmpl->get_template_parameters().end();
|
||||
++p)
|
||||
{
|
||||
write_template_parameter(*p, ctxt, nb_spaces);
|
||||
o << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize an instance of function_template_decl.
|
||||
///
|
||||
/// \param decl the instance to serialize.
|
||||
@ -1333,24 +1378,61 @@ write_function_template_decl(const shared_ptr<function_template_decl> decl,
|
||||
|
||||
o << ">\n";
|
||||
|
||||
unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
|
||||
for (list<shared_ptr<template_parameter> >::const_iterator p =
|
||||
decl->get_template_parameters().begin();
|
||||
p != decl->get_template_parameters().end();
|
||||
++p)
|
||||
{
|
||||
write_template_parameter(*p, ctxt, nb_spaces);
|
||||
o << "\n";
|
||||
}
|
||||
write_template_parameters(decl, ctxt, indent);
|
||||
|
||||
write_function_decl(decl->get_pattern(), ctxt, nb_spaces);
|
||||
write_function_decl(decl->get_pattern(), ctxt,
|
||||
get_indent_to_level(ctxt, indent, 1));
|
||||
o << "\n";
|
||||
|
||||
do_indent_to_level(ctxt, indent, 0);
|
||||
|
||||
o << "</function-template-decl>";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Serialize an instance of class_template_decl
|
||||
///
|
||||
/// \param decl a pointer to the instance of class_template_decl to serialize.
|
||||
///
|
||||
/// \param ctxt the context of the serializtion.
|
||||
///
|
||||
/// \param indent the initial number of white space to use for
|
||||
/// indentation.
|
||||
///
|
||||
/// \return true upon successful completion, false otherwise.
|
||||
static bool
|
||||
write_class_template_decl (const shared_ptr<class_template_decl> decl,
|
||||
write_context& ctxt, unsigned indent)
|
||||
{
|
||||
if (!decl)
|
||||
return false;
|
||||
|
||||
ostream& o = ctxt.get_ostream();
|
||||
|
||||
do_indent_to_level(ctxt,indent, 0);
|
||||
|
||||
o << "<class-template-decl id='" << ctxt.get_id_for_class_tmpl(decl) << "'";
|
||||
|
||||
write_location(decl, o);
|
||||
|
||||
write_visibility(decl, o);
|
||||
|
||||
o << ">\n";
|
||||
|
||||
write_template_parameters(decl, ctxt, indent);
|
||||
|
||||
write_class_decl(decl->get_pattern(), ctxt,
|
||||
get_indent_to_level(ctxt, indent, 1));
|
||||
o << "\n";
|
||||
|
||||
do_indent_to_level(ctxt, indent, 0);
|
||||
|
||||
o << "</class-template-decl>";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}//end namespace writer
|
||||
}//end namespace abigail
|
||||
|
@ -34,4 +34,5 @@ $(h)/data/test-read-write/test10.xml \
|
||||
$(h)/data/test-read-write/test11.xml \
|
||||
$(h)/data/test-read-write/test12.xml \
|
||||
$(h)/data/test-read-write/test13.xml \
|
||||
$(h)/data/test-read-write/test14.xml
|
||||
$(h)/data/test-read-write/test14.xml \
|
||||
$(h)/data/test-read-write/test15.xml
|
||||
|
17
tests/data/test-read-write/test15.xml
Normal file
17
tests/data/test-read-write/test15.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<abi-instr version='1.0'>
|
||||
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
|
||||
<class-template-decl id='class-tmpl-id-2'>
|
||||
<template-type-parameter id='type-id-3' name='T'/>
|
||||
<class-decl name='C' visibility='default' id='type-id-4'>
|
||||
<member-type access='public'>
|
||||
<typedef-decl name='TINT' type-id='type-id-1' id='type-id-5'/>
|
||||
</member-type>
|
||||
<data-member access='private'>
|
||||
<var-decl name='m_first' type-id='type-id-3'/>
|
||||
</data-member>
|
||||
<data-member access='private'>
|
||||
<var-decl name='m_second' type-id='type-id-5'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
</class-template-decl>
|
||||
</abi-instr>
|
@ -107,6 +107,10 @@ InOutSpec in_out_specs[] =
|
||||
"data/test-read-write/test14.xml",
|
||||
"output/test-read-write/test14.xml"
|
||||
},
|
||||
{
|
||||
"data/test-read-write/test15.xml",
|
||||
"output/test-read-write/test15.xml"
|
||||
},
|
||||
// This should be the last entry.
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user