public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
From: Giuliano Procida <gprocida@google.com>
To: Matthias Maennich <maennich@google.com>
Cc: Giuliano Procida via Libabigail <libabigail@sourceware.org>,
	Dodji Seketeli <dodji@seketeli.org>,
	kernel-team@android.com
Subject: Re: [PATCH] XML reader: improve XML node traversal
Date: Wed, 31 Mar 2021 17:58:24 +0100	[thread overview]
Message-ID: <CAGvU0HkfxihUwXKyUhaTb-u5J9n9Adao74PHixN9Uzr1Q+1c=w@mail.gmail.com> (raw)
In-Reply-To: <YGSGE5IeHTeJF5CT@google.com>

Thanks for the review.

Each of the long lines was a non-standard iteration over nodes and actually
deserved better.

On Wed, 31 Mar 2021 at 15:24, Matthias Maennich <maennich@google.com> wrote:

> 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!
>
>
Cheers.

v2 on the way.

Giuliano.


> 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.
>
>
It makes sense to only update the "corpus node" once, after the loop
completes. I've restructured it and indentation has been reduced as a side
effect.


> >       {
> >-      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.
>
>
I've written a very brief note at
https://sourceware.org/bugzilla/show_bug.cgi?id=26591#c6 and made the
skipping of child elements much more obvious.

(And the same for the other case.)


> >     {
> >-      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&lt;int&gt;' 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&lt;int&gt;' 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
> >
>

  reply	other threads:[~2021-03-31 16:59 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
2021-03-31 16:58   ` Giuliano Procida [this message]
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='CAGvU0HkfxihUwXKyUhaTb-u5J9n9Adao74PHixN9Uzr1Q+1c=w@mail.gmail.com' \
    --to=gprocida@google.com \
    --cc=dodji@seketeli.org \
    --cc=kernel-team@android.com \
    --cc=libabigail@sourceware.org \
    --cc=maennich@google.com \
    /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).