dwarf-reader: Don't consider top-level types as private

Message ID 87o7ycetpp.fsf@redhat.com
State New
Series dwarf-reader: Don't consider top-level types as private |

Commit Message

Dodji Seketeli June 28, 2022, 2:41 p.m. UTC

[This fixes an issue that was reported to me by Ben Woodard]

By default, the DWARF reader (wrongly) considers that any top-level
decl/type (inside a namespace) that doesn't have the DW_AT_external
attribute is a private decl/type.

It thus considers that function/variable decls that have that
attribute are public decls, and thus, the types they use are also
public.  Which is what we want.

But then, it also considers that top-level types (which never have a
DW_AT_external) are not public.  And that causes unwanted side effects
like dropping some classes on the floor.  As a result, some functions
that have those classes as parameter type would end-up being
considered as having no parameter of that type.  Oops.

This patch fixes that by considering that only function and variable
DIEs ought to have the DW_AT_external flag to be considered as public
decls.  Non-anonymous namespace are also considered as public decls.

This should fix the output of the command:

tools/fedabipkgdiff --debug --abipkgdiff build/tools/abipkgdiff --self-compare -a --from fc36 libabigail

	* src/abg-dwarf-reader.cc (die_is_public_decl): Only function and
	variable decls having the DW_AT_external, as well as non-anonymous
	namespaces are considered public decls.  The rest is considered
	(build_namespace_decl_and_add_to_ir): If the current namespace is
	private (anonymous), then its content is also private.  Otherwise,
	use die_is_public_decl to know if its content is public or not.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
 src/abg-dwarf-reader.cc | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)


diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 66bfbc3e..7c8ec012 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -6758,8 +6758,23 @@  die_access_specifier(Dwarf_Die * die, access_specifier& access)
 static bool
 die_is_public_decl(const Dwarf_Die* die)
+  if (!die)
+    return false;
   bool is_public = false;
-  die_flag_attribute(die, DW_AT_external, is_public);
+  // If this is a DW_TAG_subprogram DIE, look for the
+  // DW_AT_external attribute on it.  Otherwise, if it's a non-anonymous namespace,
+  // then it's public.  In all other cases, this should return false.
+  int tag = dwarf_tag(const_cast<Dwarf_Die*>(die));
+  if (tag == DW_TAG_subprogram || tag == DW_TAG_variable)
+    die_flag_attribute(die, DW_AT_external, is_public);
+  else if (tag == DW_TAG_namespace)
+    {
+      string name = die_name(die);
+      is_public = !name.empty();
+    }
   return is_public;
@@ -12131,7 +12146,12 @@  build_namespace_decl_and_add_to_ir(read_context&	ctxt,
     build_ir_node_from_die(ctxt, &child,
-			   /*called_from_public_decl=*/false,
+			   // If this namespace DIE is private
+			   // (anonymous) then all its content is
+			   // considered private.  Otherwise, its
+			   // public decls are considered public.
+			   /*called_from_public_decl=*/
+			   die_is_public_decl(die) && die_is_public_decl(&child),
   while (dwarf_siblingof(&child, &child) == 0);