]> sourceware.org Git - libabigail.git/commitdiff
writer: Don't forget to emit types referenced by function types
authorDodji Seketeli <dodji@redhat.com>
Thu, 14 Oct 2021 14:38:18 +0000 (16:38 +0200)
committerDodji Seketeli <dodji@redhat.com>
Mon, 18 Oct 2021 07:56:52 +0000 (09:56 +0200)
While looking into something else, I noticed that sometimes the writer
would forget to emit types referenced by function types.  Fixed thus.

* src/abg-writer.cc (write_referenced_types): Factorize out of ...
(write_translation_unit): ... here.  Also, use it to write the
types referenced by emitted function types.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
src/abg-writer.cc

index efc01fa73175149466e405ad1fd1ed0509bd5132..3848df770ef60b5aef495874a529729c5e314640 100644 (file)
@@ -2286,103 +2286,24 @@ referenced_type_should_be_emitted(const type_base *t,
   return false;
 }
 
-/// Serialize a translation unit to an output stream.
+/// Emit the types that were referenced by other emitted types.
 ///
-/// @param ctxt the context of the serialization.  It contains e.g,
-/// the output stream to serialize to.
+/// This is a sub-routine of write_translation_unit.
 ///
-/// @param tu the translation unit to serialize.
+/// @param ctxt the write context to use.
 ///
-/// @param indent how many indentation spaces to use during the
-/// serialization.
+/// @param tu the current translation unit that is being emitted.
 ///
-/// @param is_last If true, it means the TU to emit is the last one of
-/// the corpus.  If this is the case, all the remaining referenced
-/// types that were not emitted are going to be emitted here,
-/// irrespective of if they belong to this TU or not.  This is quite a
-/// hack.  Ideally, we should have a pass that walks all the TUs,
-/// detect their non-emitted referenced types, before hand.  Then,
-/// when we start emitting the TUs, we know for each TU which
-/// non-emitted referenced type should be emitted.  As we don't yet
-/// have such a pass, we do our best for now.
+/// @param indent the indentation string.
 ///
-/// @return true upon successful completion, false otherwise.
-bool
-write_translation_unit(write_context&          ctxt,
+/// @param is_last whether @p tu is the last translation unit or not.
+static void
+write_referenced_types(write_context &         ctxt,
                       const translation_unit&  tu,
                       const unsigned           indent,
                       bool                     is_last)
 {
-  if (tu.is_empty() && !is_last)
-    return false;
-
-  if (is_last
-      && tu.is_empty()
-      && ctxt.has_non_emitted_referenced_types())
-    return false;
-
-  ostream& o = ctxt.get_ostream();
   const config& c = ctxt.get_config();
-
-  do_indent(o, indent);
-
-  o << "<abi-instr";
-
-  if (tu.get_address_size() != 0)
-    o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
-
-  std::string tu_path = tu.get_path();
-  if (ctxt.get_short_locs())
-    tools_utils::base_name(tu_path, tu_path);
-  if (!tu_path.empty())
-    o << " path='" << xml::escape_xml_string(tu_path) << "'";
-
-  if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir())
-    o << " comp-dir-path='"
-      << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'";
-
-  if (tu.get_language() != translation_unit::LANG_UNKNOWN)
-    o << " language='"
-      << translation_unit_language_to_string(tu.get_language())
-      <<"'";
-
-  if (tu.is_empty() && !is_last)
-    {
-      o << "/>\n";
-      return true;
-    }
-
-  o << ">\n";
-
-  write_canonical_types_of_scope(*tu.get_global_scope(),
-                                ctxt, indent + c.get_xml_element_indent());
-
-  typedef scope_decl::declarations declarations;
-  typedef declarations::const_iterator const_iterator;
-  const declarations& d = tu.get_global_scope()->get_sorted_member_decls();
-
-  for (const_iterator i = d.begin(); i != d.end(); ++i)
-    {
-      if (type_base_sptr t = is_type(*i))
-       {
-         // Emit declaration-only classes that are needed. Some of
-         // these classes can be empty.  Those beasts can be classes
-         // that only contain member types.  They can also be classes
-         // considered "opaque".
-         if (class_decl_sptr class_type = is_class_type(t))
-           if (class_type->get_is_declaration_only()
-               && !ctxt.type_is_emitted(class_type))
-             write_type(class_type, ctxt,
-                        indent + c.get_xml_element_indent());
-         continue;
-       }
-
-      if (decl_base_sptr d = is_decl(*i))
-       if (ctxt.decl_is_emitted(d))
-         continue;
-      write_decl(*i, ctxt, indent + c.get_xml_element_indent());
-    }
-
   // Now let's handle types that were referenced, but not yet
   // emitted because they are either:
   //   1/ Types without canonical type
@@ -2479,6 +2400,106 @@ write_translation_unit(write_context&           ctxt,
        if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last))
          referenced_types_to_emit.insert(*i);
     }
+}
+
+/// Serialize a translation unit to an output stream.
+///
+/// @param ctxt the context of the serialization.  It contains e.g,
+/// the output stream to serialize to.
+///
+/// @param tu the translation unit to serialize.
+///
+/// @param indent how many indentation spaces to use during the
+/// serialization.
+///
+/// @param is_last If true, it means the TU to emit is the last one of
+/// the corpus.  If this is the case, all the remaining referenced
+/// types that were not emitted are going to be emitted here,
+/// irrespective of if they belong to this TU or not.  This is quite a
+/// hack.  Ideally, we should have a pass that walks all the TUs,
+/// detect their non-emitted referenced types, before hand.  Then,
+/// when we start emitting the TUs, we know for each TU which
+/// non-emitted referenced type should be emitted.  As we don't yet
+/// have such a pass, we do our best for now.
+///
+/// @return true upon successful completion, false otherwise.
+bool
+write_translation_unit(write_context&          ctxt,
+                      const translation_unit&  tu,
+                      const unsigned           indent,
+                      bool                     is_last)
+{
+  if (tu.is_empty() && !is_last)
+    return false;
+
+  if (is_last
+      && tu.is_empty()
+      && ctxt.has_non_emitted_referenced_types())
+    return false;
+
+  ostream& o = ctxt.get_ostream();
+  const config& c = ctxt.get_config();
+
+  do_indent(o, indent);
+
+  o << "<abi-instr";
+
+  if (tu.get_address_size() != 0)
+    o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
+
+  std::string tu_path = tu.get_path();
+  if (ctxt.get_short_locs())
+    tools_utils::base_name(tu_path, tu_path);
+  if (!tu_path.empty())
+    o << " path='" << xml::escape_xml_string(tu_path) << "'";
+
+  if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir())
+    o << " comp-dir-path='"
+      << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'";
+
+  if (tu.get_language() != translation_unit::LANG_UNKNOWN)
+    o << " language='"
+      << translation_unit_language_to_string(tu.get_language())
+      <<"'";
+
+  if (tu.is_empty() && !is_last)
+    {
+      o << "/>\n";
+      return true;
+    }
+
+  o << ">\n";
+
+  write_canonical_types_of_scope(*tu.get_global_scope(),
+                                ctxt, indent + c.get_xml_element_indent());
+
+  typedef scope_decl::declarations declarations;
+  typedef declarations::const_iterator const_iterator;
+  const declarations& d = tu.get_global_scope()->get_sorted_member_decls();
+
+  for (const_iterator i = d.begin(); i != d.end(); ++i)
+    {
+      if (type_base_sptr t = is_type(*i))
+       {
+         // Emit declaration-only classes that are needed. Some of
+         // these classes can be empty.  Those beasts can be classes
+         // that only contain member types.  They can also be classes
+         // considered "opaque".
+         if (class_decl_sptr class_type = is_class_type(t))
+           if (class_type->get_is_declaration_only()
+               && !ctxt.type_is_emitted(class_type))
+             write_type(class_type, ctxt,
+                        indent + c.get_xml_element_indent());
+         continue;
+       }
+
+      if (decl_base_sptr d = is_decl(*i))
+       if (ctxt.decl_is_emitted(d))
+         continue;
+      write_decl(*i, ctxt, indent + c.get_xml_element_indent());
+    }
+
+  write_referenced_types(ctxt, tu, indent, is_last);
 
   // Now handle all function types that were not only referenced by
   // emitted types.
@@ -2502,6 +2523,10 @@ write_translation_unit(write_context&            ctxt,
       write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent());
     }
 
+  // After we've written out the live function types, we need to write
+  // the types they referenced.
+  write_referenced_types(ctxt, tu, indent, is_last);
+
   do_indent(o, indent);
   o << "</abi-instr>\n";
 
This page took 0.047376 seconds and 5 git commands to generate.