From: Matthias Maennich <maennich@google.com>
To: Giuliano Procida <gprocida@google.com>
Cc: libabigail@sourceware.org, dodji@seketeli.org, kernel-team@android.com
Subject: Re: [PATCH] XML reader: improve XML node traversal
Date: Wed, 31 Mar 2021 15:24:19 +0100 [thread overview]
Message-ID: <YGSGE5IeHTeJF5CT@google.com> (raw)
In-Reply-To: <20210331092352.619148-1-gprocida@google.com>
On Wed, Mar 31, 2021 at 10:23:51AM +0100, Giuliano Procida wrote:
>Bug 27616: libabigail treats empty and nearly empty XML elements inconsistently
>
>The XML reader uses libxml's Reader API for parsing XML and traverses
>high-level XML nodes using reader cursor advancement. Low-level nodes
>are read into complete node trees and are traversed following
>children, next and (in one instance) parent pointers. Some
>intermediate-level nodes can be parsed both ways.
>
>A lot of code cares about node types, typically skipping over
>non-element nodes. Unfortunately, in a few places, the tracked "corpus
>node" needs to land on text (whitespace) within elements for the XML
>reader to work; stripping text nodes out causes some elements to be
>skipped. Almost all node tree traversals are very straightforward and
>can be expressed using simpler primitves than at present.
>
>This commit changes all the node tree traversals to use two node
>iteration primitives consistently. These are "first_child" and
>"next_child", both of which automatically skip text nodes. They
>replace the existing "advance_to_next_sibling_element" and *all*
>direct references to "children" and "next" nodes. The unwanted
>dependency on text within elements has been fixed.
>
>For-loops constructed with the new primitives present only element
>nodes to the loop body. This allows a lot of redundant checking for
>null / non-element nodes to be removed.
>
>These changes have been tested by using abidiff to comparing all
>current test XML files with copies where all text has been removed.
>One such test case is included in this commit.
>
> * include/abg-libxml-utils.h
> (advance_to_next_sibling_element): Remove this function.
> (first_child): Add new function. (next_child): Likewise. This
> is simpler than but functionally identical to
> advance_to_next_sibling_element.
> * src/abg-libxml-utils.cc (skip_non_elements): New function to
> skip non-element nodes in a sibling node list. (first_child):
> New function to find the first child element of a node.
> (next_child): New function to find the next sibling element of
> a node.
> * src/abg-reader.cc (walk_xml_node_to_map_type_ids): Remove
> redundant node checks. Iterate over children with first_child
> and next_child helpers. (read_translation_unit): Likewise.
> (read_translation_unit_from_input): Remove a no-longer-needed
> ->next and redundant node checks. Advance "corpus node" after
> reading the translation unit. (read_symbol_db_from_input):
> Remove a no-longer-needed ->next and advance "corpus node" as
> part of for-loop. Remove redundant node checks.
> (build_needed): Remove redundant node checks. Iterate over
> children with first_child and next_child.
> (read_elf_needed_from_input): Remove redundant node checks and
> simplify logic. Move to next element node after reading
> elf-needed node. (read_corpus_from_input): Remove no-children
> early return (which was inhibited by text nodes anyway). Set
> initial "corpus node" using first_child instead of children
> pointer. Remove redundant "corpus node" updates at end of
> function as the caller takes care of this and the node can
> become null with the new primitives.
> (read_corpus_group_from_input): Iterate over children using
> first_child and next child. Set "corpus node" for each corpus,
> not just the first. Incidentally keep going even if one corpus
> parse fails. (build_namespace_decl): Remove redundant node
> checks. Iterate over children using first_child and
> next_child. (build_elf_symbol): Remove redundant node checks.
> (build_elf_symbol_db): Iterate over children using first_child
> and next_child. (build_function_decl): Remove redundant node
> checks. Iterate over children using first_child and
> next_child. (build_function_type): Likewise.
> (build_array_type_def): Likewise. (build_enum_type_decl):
> Likewise. (build_class_decl): Likewise. (build_union_decl):
> Likewise. (build_function_tdecl): Likewise.
> (build_type_composition): Likewise.
> (build_template_tparameter): Likewise.
> (tests/data/Makefile.am): Add new test files.
> (tests/data/test-abidiff-exit/test-squished-report.txt): Add
> empty diff report.
> (tests/data/test-abidiff-exit/test-squished-v0.abi): Add test
> ABI file, containing all ELF elements.
> (tests/data/test-abidiff-exit/test-squished-v1.abi): Likewise
> and identical, except that all text has been stripped.
> (tests/test-abidiff-exit.cc): Add new test case.
>
>Signed-off-by: Giuliano Procida <gprocida@google.com>
That is a very nice simplification that comes with this fix! Thanks!
Reviewed-by: Matthias Maennich <maennich@google.com>
Cheers,
Matthias
>---
> include/abg-libxml-utils.h | 5 +-
> src/abg-libxml-utils.cc | 47 ++--
> src/abg-reader.cc | 208 +++++-------------
> tests/data/Makefile.am | 3 +
> .../test-squished-report.txt | 0
> .../test-abidiff-exit/test-squished-v0.abi | 43 ++++
> .../test-abidiff-exit/test-squished-v1.abi | 1 +
> tests/test-abidiff-exit.cc | 11 +
> 8 files changed, 136 insertions(+), 182 deletions(-)
> create mode 100644 tests/data/test-abidiff-exit/test-squished-report.txt
> create mode 100644 tests/data/test-abidiff-exit/test-squished-v0.abi
> create mode 100644 tests/data/test-abidiff-exit/test-squished-v1.abi
>
>diff --git a/include/abg-libxml-utils.h b/include/abg-libxml-utils.h
>index 69e940f6..f87ee5a0 100644
>--- a/include/abg-libxml-utils.h
>+++ b/include/abg-libxml-utils.h
>@@ -82,7 +82,10 @@ int get_xml_node_depth(xmlNodePtr);
> reinterpret_cast<char*>(xml_char_str.get())
>
> xmlNodePtr
>-advance_to_next_sibling_element(xmlNodePtr node);
>+first_child(xmlNodePtr node);
>+
>+xmlNodePtr
>+next_child(xmlNodePtr node);
>
> void
> escape_xml_string(const std::string& str,
>diff --git a/src/abg-libxml-utils.cc b/src/abg-libxml-utils.cc
>index a1acff1f..baea25ac 100644
>--- a/src/abg-libxml-utils.cc
>+++ b/src/abg-libxml-utils.cc
>@@ -413,40 +413,39 @@ unescape_xml_comment(const std::string& str)
> return result;
> }
>
>-/// Maybe get the next sibling element node of an XML node, or stay to the sam
>+/// Skip until we reach an XML element node or run out of (child) nodes.
> ///
>-/// If there is no next sibling xml element node, the function returns
>-/// the initial node.
>+/// @param a pointer to a node.
> ///
>-/// @param node the initial node to consider.
>-///
>-/// @return the next sibling node or the initial node @p node.
>-static xmlNodePtr
>-go_to_next_sibling_element_or_stay(xmlNodePtr node)
>+/// @return a pointer to an XML element node or nil.
>+xmlNodePtr
>+skip_non_elements(xmlNodePtr node)
> {
>- xmlNodePtr n;
>- for (n = node; n; n = n->next)
>- {
>- if (n->type == XML_ELEMENT_NODE)
>- break;
>- }
>- return n ? n : node;
>+ while (node && node->type != XML_ELEMENT_NODE)
>+ node = node->next;
>+ return node;
> }
>
>-/// Get the next sibling element node of an XML node.
>+/// Get the first child element of an XML node.
> ///
>-/// If there is no next sibling xml element node, the function returns nil.
>+/// @param a pointer to the node whose children are to be perused.
> ///
>-/// @param node the XML node to consider.
>+/// @return a pointer to the first XML element child of @p node or nil.
>+xmlNodePtr
>+first_child(xmlNodePtr node)
>+{
>+ return skip_non_elements(node->children);
>+}
>+
>+/// Get the next sibling element of an XML node.
> ///
>-/// @return the next sibling element node or nil.
>+/// @param a pointer to the XML node whose following siblings are to be perused.
>+///
>+/// @return a pointer to the next sibling element of @p node or nil.
> xmlNodePtr
>-advance_to_next_sibling_element(xmlNodePtr node)
>+next_child(xmlNodePtr node)
> {
>- xmlNodePtr n = go_to_next_sibling_element_or_stay(node->next);
>- if (n == 0 || n->type != XML_ELEMENT_NODE)
>- return 0;
>- return n;
>+ return skip_non_elements(node->next);
> }
>
> }//end namespace xml
>diff --git a/src/abg-reader.cc b/src/abg-reader.cc
>index 3e552864..a143eb58 100644
>--- a/src/abg-reader.cc
>+++ b/src/abg-reader.cc
>@@ -1343,18 +1343,13 @@ static void
> walk_xml_node_to_map_type_ids(read_context& ctxt,
> xmlNodePtr node)
> {
>- xmlNodePtr n = node;
>-
>- if (!n || n->type != XML_ELEMENT_NODE)
>- return;
>-
>- if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "id"))
>+ if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
> {
> string id = CHAR_STR(s);
>- ctxt.map_id_and_node(id, n);
>+ ctxt.map_id_and_node(id, node);
> }
>
>- for (n = n->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> walk_xml_node_to_map_type_ids(ctxt, n);
> }
>
>@@ -1396,12 +1391,8 @@ read_translation_unit(read_context& ctxt, translation_unit& tu, xmlNodePtr node)
> || !ctxt.get_corpus())
> walk_xml_node_to_map_type_ids(ctxt, node);
>
>- for (xmlNodePtr n = node->children; n; n = n->next)
>- {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>- handle_element_node(ctxt, n, /*add_decl_to_scope=*/true);
>- }
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
>+ handle_element_node(ctxt, n, /*add_decl_to_scope=*/true);
>
> ctxt.pop_scope_or_abort(tu.get_global_scope());
>
>@@ -1495,16 +1486,9 @@ read_translation_unit_from_input(read_context& ctxt)
> else
> {
> node = 0;
>- for (xmlNodePtr n = ctxt.get_corpus_node()->next; n; n = n->next)
>- {
>- if (!n
>- || n->type != XML_ELEMENT_NODE)
>- continue;
>- if (!xmlStrEqual(n->name, BAD_CAST("abi-instr")))
>- return nil;
>- node = n;
>- break;
>- }
>+ xmlNodePtr n = ctxt.get_corpus_node();
>+ if (n && xmlStrEqual(n->name, BAD_CAST("abi-instr")))
>+ node = n;
> }
>
> if (node == 0)
>@@ -1517,9 +1501,9 @@ read_translation_unit_from_input(read_context& ctxt)
> // case, after that unexpected call to read_translation_unit(), the
> // current corpus node of the context is going to point to that
> // translation unit that has been read under the hood. Let's set
>- // the corpus node to the one we initially called
>+ // the corpus node to just after the one we initially called
> // read_translation_unit() on here.
>- ctxt.set_corpus_node(node);
>+ ctxt.set_corpus_node(xml::next_child(node));
> return tu;
> }
>
>@@ -1593,11 +1577,8 @@ read_symbol_db_from_input(read_context& ctxt,
> xmlTextReaderNext(reader.get());
> }
> else
>- for (xmlNodePtr n = ctxt.get_corpus_node()->next; n; n = n->next)
>+ for (xmlNodePtr n = ctxt.get_corpus_node(); n; n = xml::next_child(n), ctxt.set_corpus_node(n))
That line looks a little long.
> {
>- if (!n || n->type != XML_ELEMENT_NODE)
>- continue;
>-
> bool has_fn_syms = false, has_var_syms = false;
> if (xmlStrEqual(n->name, BAD_CAST("elf-function-symbols")))
> has_fn_syms = true;
>@@ -1605,7 +1586,6 @@ read_symbol_db_from_input(read_context& ctxt,
> has_var_syms = true;
> else
> break;
>- ctxt.set_corpus_node(n);
> if (has_fn_syms)
> {
> fn_symdb = build_elf_symbol_db(ctxt, n, true);
>@@ -1636,16 +1616,12 @@ read_symbol_db_from_input(read_context& ctxt,
> static bool
> build_needed(xmlNode* node, vector<string>& needed)
> {
>- if (!node)
>- return false;
>-
>- if (!node || !xmlStrEqual(node->name,BAD_CAST("elf-needed")))
>+ if (!xmlStrEqual(node->name,BAD_CAST("elf-needed")))
> return false;
>
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE
>- || !xmlStrEqual(n->name, BAD_CAST("dependency")))
>+ if (!xmlStrEqual(n->name, BAD_CAST("dependency")))
> continue;
>
> string name;
>@@ -1693,27 +1669,19 @@ read_elf_needed_from_input(read_context& ctxt,
> return false;
>
> node = xmlTextReaderExpand(reader.get());
>- if (!node)
>- return false;
> }
> else
> {
>- for (xmlNodePtr n = ctxt.get_corpus_node()->next; n; n = n->next)
>- {
>- if (!n || n->type != XML_ELEMENT_NODE)
>- continue;
>- if (!xmlStrEqual(n->name, BAD_CAST("elf-needed")))
>- return false;
>- node = n;
>- break;
>- }
>+ xmlNodePtr n = ctxt.get_corpus_node();
>+ if (n && xmlStrEqual(n->name, BAD_CAST("elf-needed")))
>+ node = n;
> }
>
> bool result = false;
> if (node)
> {
> result = build_needed(node, needed);
>- ctxt.set_corpus_node(node);
>+ ctxt.set_corpus_node(xml::next_child(node));
> }
>
> return result;
>@@ -1917,10 +1885,7 @@ read_corpus_from_input(read_context& ctxt)
> corp.set_soname(reinterpret_cast<char*>(soname_str.get()));
> }
>
>- if (!node->children)
>- return nil;
>-
>- ctxt.set_corpus_node(node->children);
>+ ctxt.set_corpus_node(xml::first_child(node));
>
> corpus& corp = *ctxt.get_corpus();
>
>@@ -1986,17 +1951,6 @@ read_corpus_from_input(read_context& ctxt)
> // call at the beginning of the function.
> xmlTextReaderNext(reader.get());
> }
>- else
>- {
>- node = ctxt.get_corpus_node();
>- node = xml::advance_to_next_sibling_element(node);
>- if (!node)
>- {
>- node = ctxt.get_corpus_node();
>- node = xml::advance_to_next_sibling_element(node->parent);
>- }
>- ctxt.set_corpus_node(node);
>- }
>
> return ctxt.get_corpus();
> }
>@@ -2046,13 +2000,13 @@ read_corpus_group_from_input(read_context& ctxt)
> if (!node)
> return nil;
>
>- //node = xml::get_first_element_sibling_if_text(node->children);
>- node = xml::advance_to_next_sibling_element(node->children);
>- ctxt.set_corpus_node(node);
>-
>- corpus_sptr corp;
>- while ((corp = read_corpus_from_input(ctxt)))
>- ctxt.get_corpus_group()->add_corpus(corp);
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
>+ {
>+ ctxt.set_corpus_node(n);
>+ corpus_sptr corp = read_corpus_from_input(ctxt);
>+ if (corp)
>+ ctxt.get_corpus_group()->add_corpus(corp);
>+ }
>
> xmlTextReaderNext(reader.get());
>
>@@ -2738,12 +2692,8 @@ build_namespace_decl(read_context& ctxt,
> ctxt.push_decl_to_current_scope(decl, add_to_current_scope);
> ctxt.map_xml_node_to_decl(node, decl);
>
>- for (xmlNodePtr n = node->children; n; n = n->next)
>- {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>- handle_element_node(ctxt, n, /*add_to_current_scope=*/true);
>- }
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
>+ handle_element_node(ctxt, n, /*add_to_current_scope=*/true);
>
> ctxt.pop_scope_or_abort(decl);
>
>@@ -2767,9 +2717,7 @@ build_elf_symbol(read_context& ctxt, const xmlNodePtr node,
> {
> elf_symbol_sptr nil;
>
>- if (!node
>- || node->type != XML_ELEMENT_NODE
>- || !xmlStrEqual(node->name, BAD_CAST("elf-symbol")))
>+ if (!xmlStrEqual(node->name, BAD_CAST("elf-symbol")))
> return nil;
>
> string name;
>@@ -2928,7 +2876,7 @@ build_elf_symbol_db(read_context& ctxt,
> xml_node_ptr_elf_symbol_sptr_map_type xml_node_ptr_elf_symbol_map;
>
> elf_symbol_sptr sym;
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
> if ((sym = build_elf_symbol(ctxt, n, /*drop_if_suppress=*/true)))
> {
>@@ -3094,12 +3042,9 @@ build_function_decl(read_context& ctxt,
> std::vector<function_decl::parameter_sptr> parms;
> type_base_sptr return_type = env->get_void_type();
>
>- for (xmlNodePtr n = node->children; n ; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
>- else if (xmlStrEqual(n->name, BAD_CAST("parameter")))
>+ if (xmlStrEqual(n->name, BAD_CAST("parameter")))
> {
> if (function_decl::parameter_sptr p =
> build_function_parameter(ctxt, n))
>@@ -3789,12 +3734,9 @@ build_function_type(read_context& ctxt,
> ctxt.get_translation_unit()->bind_function_type_life_time(fn_type);
> ctxt.key_type_decl(fn_type, id);
>
>- for (xmlNodePtr n = node->children; n ; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
>- else if (xmlStrEqual(n->name, BAD_CAST("parameter")))
>+ if (xmlStrEqual(n->name, BAD_CAST("parameter")))
> {
> if (function_decl::parameter_sptr p =
> build_function_parameter(ctxt, n))
>@@ -4025,12 +3967,9 @@ build_array_type_def(read_context& ctxt,
> read_location(ctxt, node, loc);
> array_type_def::subranges_type subranges;
>
>- for (xmlNodePtr n = node->children; n ; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
>- else if (xmlStrEqual(n->name, BAD_CAST("subrange")))
>+ if (xmlStrEqual(n->name, BAD_CAST("subrange")))
> {
> if (array_type_def::subrange_sptr s =
> build_subrange_type(ctxt, n))
>@@ -4183,11 +4122,8 @@ build_enum_type_decl(read_context& ctxt,
>
> string base_type_id;
> enum_type_decl::enumerators enums;
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (xmlStrEqual(n->name, BAD_CAST("underlying-type")))
> {
> xml_char_sptr a = xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id")));
>@@ -4554,11 +4490,8 @@ build_class_decl(read_context& ctxt,
> decl->set_naming_typedef(naming_typedef);
> }
>
>- for (xmlNodePtr n = node->children; !is_decl_only && n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); !is_decl_only && n; n = xml::next_child(n))
Likewise.
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (xmlStrEqual(n->name, BAD_CAST("base-class")))
> {
> access_specifier access =
>@@ -4605,11 +4538,8 @@ build_class_decl(read_context& ctxt,
>
> ctxt.map_xml_node_to_decl(n, decl);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (type_base_sptr t =
> build_type(ctxt, p, /*add_to_current_scope=*/true))
> {
>@@ -4643,11 +4573,8 @@ build_class_decl(read_context& ctxt,
> bool is_static = false;
> read_static(n, is_static);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (var_decl_sptr v =
> build_var_decl(ctxt, p, /*add_to_cur_scope=*/false))
> {
>@@ -4701,11 +4628,8 @@ build_class_decl(read_context& ctxt,
> bool is_ctor = false, is_dtor = false, is_const = false;
> read_cdtor_const(n, is_ctor, is_dtor, is_const);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (function_decl_sptr f =
> build_function_decl_if_not_suppressed(ctxt, p, decl,
> /*add_to_cur_sc=*/true))
>@@ -4740,11 +4664,8 @@ build_class_decl(read_context& ctxt,
> bool is_ctor = false, is_dtor = false, is_const = false;
> read_cdtor_const(n, is_ctor, is_dtor, is_const);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (shared_ptr<function_tdecl> f =
> build_function_tdecl(ctxt, p,
> /*add_to_current_scope=*/true))
>@@ -4954,11 +4875,8 @@ build_union_decl(read_context& ctxt,
> ctxt.map_xml_node_to_decl(node, decl);
> ctxt.key_type_decl(decl, id);
>
>- for (xmlNodePtr n = node->children; !is_decl_only && n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); !is_decl_only && n; n = xml::next_child(n))
Likewise.
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (xmlStrEqual(n->name, BAD_CAST("member-type")))
> {
> access_specifier access = private_access;
>@@ -4966,11 +4884,8 @@ build_union_decl(read_context& ctxt,
>
> ctxt.map_xml_node_to_decl(n, decl);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (type_base_sptr t =
> build_type(ctxt, p, /*add_to_current_scope=*/true))
> {
>@@ -4998,11 +4913,8 @@ build_union_decl(read_context& ctxt,
> bool is_static = false;
> read_static(n, is_static);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (var_decl_sptr v =
> build_var_decl(ctxt, p, /*add_to_cur_scope=*/false))
> {
>@@ -5040,11 +4952,8 @@ build_union_decl(read_context& ctxt,
> bool is_ctor = false, is_dtor = false, is_const = false;
> read_cdtor_const(n, is_ctor, is_dtor, is_const);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (function_decl_sptr f =
> build_function_decl_if_not_suppressed(ctxt, p, decl,
> /*add_to_cur_sc=*/true))
>@@ -5073,11 +4982,8 @@ build_union_decl(read_context& ctxt,
> bool is_ctor = false, is_dtor = false, is_const = false;
> read_cdtor_const(n, is_ctor, is_dtor, is_const);
>
>- for (xmlNodePtr p = n->children; p; p = p->next)
>+ for (xmlNodePtr p = xml::first_child(n); p; p = xml::next_child(p))
> {
>- if (p->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (function_tdecl_sptr f =
> build_function_tdecl(ctxt, p,
> /*add_to_current_scope=*/true))
>@@ -5152,11 +5058,8 @@ build_function_tdecl(read_context& ctxt,
> ctxt.push_decl_to_current_scope(fn_tmpl_decl, add_to_current_scope);
>
> unsigned parm_index = 0;
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (template_parameter_sptr parm =
> build_template_parameter(ctxt, n, parm_index, fn_tmpl_decl))
> {
>@@ -5216,11 +5119,8 @@ build_class_tdecl(read_context& ctxt,
> ctxt.push_decl_to_current_scope(class_tmpl, add_to_current_scope);
>
> unsigned parm_index = 0;
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (template_parameter_sptr parm=
> build_template_parameter(ctxt, n, parm_index, class_tmpl))
> {
>@@ -5335,11 +5235,8 @@ build_type_composition(read_context& ctxt,
> ctxt.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(result),
> /*add_to_current_scope=*/true);
>
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if ((composed_type =
> build_pointer_type_def(ctxt, n,
> /*add_to_current_scope=*/true))
>@@ -5465,11 +5362,8 @@ build_template_tparameter(read_context& ctxt,
>
> // Go parse template parameters that are children nodes
> int parm_index = 0;
>- for (xmlNodePtr n = node->children; n; n = n->next)
>+ for (xmlNodePtr n = xml::first_child(node); n; n = xml::next_child(n))
> {
>- if (n->type != XML_ELEMENT_NODE)
>- continue;
>-
> if (shared_ptr<template_parameter> p =
> build_template_parameter(ctxt, n, parm_index, result))
> {
>diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
>index 4fb2d6a4..7bdae7bf 100644
>--- a/tests/data/Makefile.am
>+++ b/tests/data/Makefile.am
>@@ -197,6 +197,9 @@ test-abidiff-exit/test-non-leaf-array-v0.o \
> test-abidiff-exit/test-non-leaf-array-v1.c \
> test-abidiff-exit/test-non-leaf-array-v1.o \
> test-abidiff-exit/test-non-leaf-array-report.txt \
>+test-abidiff-exit/test-squished-v0.abi \
>+test-abidiff-exit/test-squished-v1.abi \
>+test-abidiff-exit/test-squished-report.txt \
> \
> test-diff-dwarf/test0-v0.cc \
> test-diff-dwarf/test0-v0.o \
>diff --git a/tests/data/test-abidiff-exit/test-squished-report.txt b/tests/data/test-abidiff-exit/test-squished-report.txt
>new file mode 100644
>index 00000000..e69de29b
>diff --git a/tests/data/test-abidiff-exit/test-squished-v0.abi b/tests/data/test-abidiff-exit/test-squished-v0.abi
>new file mode 100644
>index 00000000..6b3d0460
>--- /dev/null
>+++ b/tests/data/test-abidiff-exit/test-squished-v0.abi
>@@ -0,0 +1,43 @@
>+<abi-corpus version='2.0' path='data/test-read-dwarf/test6.so'>
>+ <elf-needed>
>+ <dependency name='libstdc++.so.6'/>
>+ <dependency name='libm.so.6'/>
>+ <dependency name='libgcc_s.so.1'/>
>+ <dependency name='libc.so.6'/>
>+ </elf-needed>
>+ <elf-function-symbols>
>+ <elf-symbol name='_Z3barv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>+ <elf-symbol name='_Z4blehv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>+ <elf-symbol name='_ZN1B3fooEv' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>+ <elf-symbol name='_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>+ <elf-symbol name='_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>+ </elf-function-symbols>
>+ <elf-variable-symbols>
>+ <elf-symbol name='_ZN1CIiE3barE' size='4' type='object-type' binding='gnu-unique-binding' visibility='default-visibility' is-defined='yes'/>
>+ <elf-symbol name='_ZZN1B3fooEvE1a' size='4' type='object-type' binding='gnu-unique-binding' visibility='default-visibility' is-defined='yes'/>
>+ </elf-variable-symbols>
>+ <abi-instr address-size='64' path='test6.cc' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C_plus_plus'>
>+ <type-decl name='int' size-in-bits='32' id='type-id-1'/>
>+ <class-decl name='B' size-in-bits='8' is-struct='yes' visibility='default' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='9' column='1' id='type-id-2'>
>+ <member-function access='public'>
>+ <function-decl name='foo' mangled-name='_ZN1B3fooEv' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='11' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_ZN1B3fooEv'>
>+ <parameter type-id='type-id-3' name='this' is-artificial='yes'/>
>+ <return type-id='type-id-1'/>
>+ </function-decl>
>+ </member-function>
>+ </class-decl>
>+ <class-decl name='C<int>' size-in-bits='8' is-struct='yes' visibility='default' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='26' column='1' id='type-id-4'>
>+ <data-member access='public' static='yes'>
>+ <var-decl name='bar' type-id='type-id-1' mangled-name='_ZN1CIiE3barE' visibility='default' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='31' column='1' elf-symbol-id='_ZN1CIiE3barE'/>
>+ </data-member>
>+ </class-decl>
>+ <pointer-type-def type-id='type-id-2' size-in-bits='64' id='type-id-5'/>
>+ <qualified-type-def type-id='type-id-5' const='yes' id='type-id-3'/>
>+ <function-decl name='bar' mangled-name='_Z3barv' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='19' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_Z3barv'>
>+ <return type-id='type-id-1'/>
>+ </function-decl>
>+ <function-decl name='bleh' mangled-name='_Z4blehv' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='34' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_Z4blehv'>
>+ <return type-id='type-id-1'/>
>+ </function-decl>
>+ </abi-instr>
>+</abi-corpus>
>diff --git a/tests/data/test-abidiff-exit/test-squished-v1.abi b/tests/data/test-abidiff-exit/test-squished-v1.abi
>new file mode 100644
>index 00000000..3ffa272b
>--- /dev/null
>+++ b/tests/data/test-abidiff-exit/test-squished-v1.abi
>@@ -0,0 +1 @@
>+<abi-corpus version='2.0' path='data/test-read-dwarf/test6.so'><elf-needed><dependency name='libstdc++.so.6'/><dependency name='libm.so.6'/><dependency name='libgcc_s.so.1'/><dependency name='libc.so.6'/></elf-needed><elf-function-symbols><elf-symbol name='_Z3barv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/><elf-symbol name='_Z4blehv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/><elf-symbol name='_ZN1B3fooEv' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/><elf-symbol name='_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/><elf-symbol name='_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/></elf-function-symbols><elf-variable-symbols><elf-symbol name='_ZN1CIiE3barE' size='4' type='object-type' binding='gnu-unique-binding' visibility='default-visibility' is-defined='yes'/><elf-symbol name='_ZZN1B3fooEvE1a' size='4' type='object-type' binding='gnu-unique-binding' visibility='default-visibility' is-defined='yes'/></elf-variable-symbols><abi-instr address-size='64' path='test6.cc' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C_plus_plus'><type-decl name='int' size-in-bits='32' id='type-id-1'/><class-decl name='B' size-in-bits='8' is-struct='yes' visibility='default' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='9' column='1' id='type-id-2'><member-function access='public'><function-decl name='foo' mangled-name='_ZN1B3fooEv' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='11' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_ZN1B3fooEv'><parameter type-id='type-id-3' name='this' is-artificial='yes'/><return type-id='type-id-1'/></function-decl></member-function></class-decl><class-decl name='C<int>' size-in-bits='8' is-struct='yes' visibility='default' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='26' column='1' id='type-id-4'><data-member access='public' static='yes'><var-decl name='bar' type-id='type-id-1' mangled-name='_ZN1CIiE3barE' visibility='default' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='31' column='1' elf-symbol-id='_ZN1CIiE3barE'/></data-member></class-decl><pointer-type-def type-id='type-id-2' size-in-bits='64' id='type-id-5'/><qualified-type-def type-id='type-id-5' const='yes' id='type-id-3'/><function-decl name='bar' mangled-name='_Z3barv' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='19' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_Z3barv'><return type-id='type-id-1'/></function-decl><function-decl name='bleh' mangled-name='_Z4blehv' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test6.cc' line='34' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_Z4blehv'><return type-id='type-id-1'/></function-decl></abi-instr></abi-corpus>
>\ No newline at end of file
>diff --git a/tests/test-abidiff-exit.cc b/tests/test-abidiff-exit.cc
>index 4283e145..f1526b9e 100644
>--- a/tests/test-abidiff-exit.cc
>+++ b/tests/test-abidiff-exit.cc
>@@ -392,6 +392,17 @@ InOutSpec in_out_specs[] =
> "data/test-abidiff-exit/test-non-leaf-array-report.txt",
> "output/test-abidiff-exit/test-non-leaf-array-report.txt"
> },
>+ {
>+ "data/test-abidiff-exit/test-squished-v0.abi",
>+ "data/test-abidiff-exit/test-squished-v1.abi",
>+ "",
>+ "",
>+ "",
>+ "--harmless",
>+ abigail::tools_utils::ABIDIFF_OK,
>+ "data/test-abidiff-exit/test-squished-report.txt",
>+ "output/test-abidiff-exit/test-squished-report.txt"
>+ },
> {0, 0, 0 ,0, 0, 0, abigail::tools_utils::ABIDIFF_OK, 0, 0}
> };
>
>--
>2.31.0.291.g576ba9dcdaf-goog
>
next prev parent reply other threads:[~2021-03-31 14:24 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-31 9:23 Giuliano Procida
2021-03-31 14:24 ` Matthias Maennich [this message]
2021-03-31 16:58 ` Giuliano Procida
2021-03-31 17:04 ` [PATCH v2] " Giuliano Procida
2021-04-06 11:48 ` Dodji Seketeli
2021-04-06 14:35 ` Giuliano Procida
2021-04-06 16:22 ` [PATCH v3] " Giuliano Procida
2021-04-06 17:39 ` [PATCH v4] " Giuliano Procida
2021-04-15 14:12 ` [PATCH v2, " Dodji Seketeli
2021-04-16 12:03 ` Giuliano Procida
2021-04-19 13:40 ` Dodji Seketeli
2021-04-19 14:00 ` Subject: [PATCH 1/3] reader: Handle 'abi-corpus' element being possibly empty Dodji Seketeli
2021-04-19 14:01 ` [PATCH 2/3] reader: Use xmlFirstElementChild and xmlNextElementSibling rather than xml::advance_to_next_sibling_element Dodji Seketeli
2021-04-19 14:03 ` [PATCH 3/3] reader: Use xmlFirstElementChild/xmlNextElementSibling to iterate over children elements Dodji Seketeli
2021-04-20 6:52 ` Giuliano Procida
2021-04-20 9:46 ` Dodji Seketeli
2021-05-03 15:18 ` Dodji Seketeli
2021-05-04 11:13 ` Giuliano Procida
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YGSGE5IeHTeJF5CT@google.com \
--to=maennich@google.com \
--cc=dodji@seketeli.org \
--cc=gprocida@google.com \
--cc=kernel-team@android.com \
--cc=libabigail@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).