dwarf-reader: Canonicalize opaque enums and classes

This issue was reported in bug https://sourceware.org/bugzilla/show_bug.cgi?id=27700.

When we construct an opaque type (triggered by the use of
--drop-private-types along with the --headers-dir option on abidw, for
instance) with get_opaque_version_of_type we forget to canonicalize
the resulting type.

Later, at abixml emitting time (for instance)
hash_as_canonical_type_or_constant would rightfully abort because the
type wasn't canonicalized.  We want all types (okay, modulo one
exception) in the system to be canonicalized.

This patch fixes the problem by canonicalizing opaque types.

	* src/abg-dwarf-reader.cc (build_ir_node_from_die): Canonicalize
	opaque enums and classes.
	* tests/data/test-read-dwarf/PR27700/include-dir/priv.h: New test
	header file.
	* tests/data/test-read-dwarf/PR27700/include-dir/pub.h: Likewise
	* tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h: Likewise.
	* tests/data/test-read-dwarf/PR27700/test-PR27700.o: New binary
	input file.
	* tests/data/test-read-dwarf/PR27700/test-PR27700.abi: Reference
	abi file of the binary above.
	* tests/data/test-read-dwarf/PR27700/test-PR27700.c: Source file
	of the binary above.
	* tests/data/Makefile.am: Add the test material above to source
	distribution.
	* tests/test-read-dwarf.cc (InOutSpec::in_public_headers_path):
	Add new data member.
	(in_out_specs): Adjust to reflect the new data member in the
	InOutSpec type.  Add a new test input.
	(set_suppressions_from_headers): Define new static function.
	(test_task::perform): Use the content of the new
	InOutSpec::in_public_headers_path to construct and add
	"--headers-dir <headers-dir> --drop-private-types" to the options
	of the abidw program run.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 47d63a7..604c76e 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -14807,13 +14807,16 @@
 	bool type_suppressed =
 	  type_is_suppressed(ctxt, scope, die, type_is_private);
 	if (type_suppressed && type_is_private)
-	  // The type is suppressed because it's private.  If other
-	  // non-suppressed and declaration-only instances of this
-	  // type exist in the current corpus, then it means those
-	  // non-suppressed instances are opaque versions of the
-	  // suppressed private type.  Lets return one of these opaque
-	  // types then.
-	  result = get_opaque_version_of_type(ctxt, scope, die, where_offset);
+	  {
+	    // The type is suppressed because it's private.  If other
+	    // non-suppressed and declaration-only instances of this
+	    // type exist in the current corpus, then it means those
+	    // non-suppressed instances are opaque versions of the
+	    // suppressed private type.  Lets return one of these opaque
+	    // types then.
+	    result = get_opaque_version_of_type(ctxt, scope, die, where_offset);
+	    maybe_canonicalize_type(is_type(result), ctxt);
+	  }
 	else if (!type_suppressed)
 	  {
 	    enum_type_decl_sptr e = build_enum_type(ctxt, die, scope,
@@ -14837,13 +14840,16 @@
 	  type_is_suppressed(ctxt, scope, die, type_is_private);
 
 	if (type_suppressed && type_is_private)
-	  // The type is suppressed because it's private.  If other
-	  // non-suppressed and declaration-only instances of this
-	  // type exist in the current corpus, then it means those
-	  // non-suppressed instances are opaque versions of the
-	  // suppressed private type.  Lets return one of these opaque
-	  // types then.
-	  result = get_opaque_version_of_type(ctxt, scope, die, where_offset);
+	  {
+	    // The type is suppressed because it's private.  If other
+	    // non-suppressed and declaration-only instances of this
+	    // type exist in the current corpus, then it means those
+	    // non-suppressed instances are opaque versions of the
+	    // suppressed private type.  Lets return one of these opaque
+	    // types then.
+	    result = get_opaque_version_of_type(ctxt, scope, die, where_offset);
+	    maybe_canonicalize_type(is_type(result), ctxt);
+	  }
 	else if (!type_suppressed)
 	  {
 	    Dwarf_Die spec_die;
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 53faec6..576309e 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -556,6 +556,12 @@
 test-read-dwarf/test-suppressed-alias.o \
 test-read-dwarf/test-suppressed-alias.o.abi \
 test-read-dwarf/test-suppressed-alias.suppr \
+test-read-dwarf/PR27700/include-dir/priv.h  \
+test-read-dwarf/PR27700/include-dir/pub.h  \
+test-read-dwarf/PR27700/pub-incdir/inc.h  \
+test-read-dwarf/PR27700/test-PR27700.abi  \
+test-read-dwarf/PR27700/test-PR27700.c  \
+test-read-dwarf/PR27700/test-PR27700.o  \
 \
 test-annotate/test0.abi			\
 test-annotate/test1.abi			\
diff --git a/tests/data/test-read-dwarf/PR27700/include-dir/priv.h b/tests/data/test-read-dwarf/PR27700/include-dir/priv.h
new file mode 100644
index 0000000..e76683d
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR27700/include-dir/priv.h
@@ -0,0 +1,7 @@
+enum foo
+{
+  foo_e0,
+  foo_e1,
+  foo_e2,
+  foo_e3
+};
diff --git a/tests/data/test-read-dwarf/PR27700/include-dir/pub.h b/tests/data/test-read-dwarf/PR27700/include-dir/pub.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR27700/include-dir/pub.h
diff --git a/tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h b/tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h
diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.abi b/tests/data/test-read-dwarf/PR27700/test-PR27700.abi
new file mode 100644
index 0000000..5c49e36
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR27700/test-PR27700.abi
@@ -0,0 +1,17 @@
+<abi-corpus version='2.0' path='data/test-read-dwarf/PR27700/test-PR27700.o'>
+  <elf-function-symbols>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' path='test-PR27700.c' comp-dir-path='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700' language='LANG_C11'>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
+    <type-decl name='void' id='48b5725f'/>
+    <enum-decl name='foo' is-artificial='yes' filepath='include-dir/priv.h' line='1' column='1' id='022218d8'>
+      <underlying-type type-id='9cac1fee'/>
+    </enum-decl>
+    <pointer-type-def type-id='022218d8' size-in-bits='64' id='8750e847'/>
+    <function-decl name='foo' mangled-name='foo' filepath='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700/test-PR27700.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
+      <parameter type-id='8750e847' name='c' filepath='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700/test-PR27700.c' line='4' column='1'/>
+      <return type-id='48b5725f'/>
+    </function-decl>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.c b/tests/data/test-read-dwarf/PR27700/test-PR27700.c
new file mode 100644
index 0000000..b44a322
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR27700/test-PR27700.c
@@ -0,0 +1,6 @@
+#include "include-dir/priv.h"
+
+void
+foo(enum foo* c __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.o b/tests/data/test-read-dwarf/PR27700/test-PR27700.o
new file mode 100644
index 0000000..3f084d2
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR27700/test-PR27700.o
Binary files differ
diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
index e327909..a04cef0 100644
--- a/tests/test-read-dwarf.cc
+++ b/tests/test-read-dwarf.cc
@@ -46,6 +46,7 @@
 {
   const char* in_elf_path;
   const char* in_suppr_spec_path;
+  const char* in_public_headers_path;
   type_id_style_kind type_id_style;
   const char* in_abi_path;
   const char* out_abi_path;
@@ -57,6 +58,7 @@
   {
     "data/test-read-dwarf/test0",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test0.abi",
     "output/test-read-dwarf/test0.abi"
@@ -64,6 +66,7 @@
   {
     "data/test-read-dwarf/test0",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test0.hash.abi",
     "output/test-read-dwarf/test0.hash.abi"
@@ -71,6 +74,7 @@
   {
     "data/test-read-dwarf/test1",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test1.abi",
     "output/test-read-dwarf/test1.abi"
@@ -78,6 +82,7 @@
   {
     "data/test-read-dwarf/test1",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test1.hash.abi",
     "output/test-read-dwarf/test1.hash.abi"
@@ -85,6 +90,7 @@
   {
     "data/test-read-dwarf/test2.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test2.so.abi",
     "output/test-read-dwarf/test2.so.abi"
@@ -92,6 +98,7 @@
   {
     "data/test-read-dwarf/test2.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test2.so.hash.abi",
     "output/test-read-dwarf/test2.so.hash.abi"
@@ -99,6 +106,7 @@
   {
     "data/test-read-dwarf/test3.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test3.so.abi",
     "output/test-read-dwarf/test3.so.abi"
@@ -106,6 +114,7 @@
   {
     "data/test-read-dwarf/test3.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test3.so.hash.abi",
     "output/test-read-dwarf/test3.so.hash.abi"
@@ -114,6 +123,7 @@
   {
     "data/test-read-dwarf/test3.so",
     "data/test-read-dwarf/test3-alias-1.suppr",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test3-alias-1.so.hash.abi",
     "output/test-read-dwarf/test3-alias-1.so.hash.abi"
@@ -122,6 +132,7 @@
   {
     "data/test-read-dwarf/test3.so",
     "data/test-read-dwarf/test3-alias-2.suppr",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test3-alias-2.so.hash.abi",
     "output/test-read-dwarf/test3-alias-2.so.hash.abi"
@@ -130,6 +141,7 @@
   {
     "data/test-read-dwarf/test3.so",
     "data/test-read-dwarf/test3-alias-3.suppr",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test3-alias-3.so.hash.abi",
     "output/test-read-dwarf/test3-alias-3.so.hash.abi"
@@ -138,6 +150,7 @@
   {
     "data/test-read-dwarf/test3.so",
     "data/test-read-dwarf/test3-alias-4.suppr",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test3-alias-4.so.hash.abi",
     "output/test-read-dwarf/test3-alias-4.so.hash.abi"
@@ -146,6 +159,7 @@
   {
     "data/test-read-dwarf/test-suppressed-alias.o",
     "data/test-read-dwarf/test-suppressed-alias.suppr",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test-suppressed-alias.o.abi",
     "output/test-read-dwarf/test-suppressed-alias.o.abi",
@@ -153,6 +167,7 @@
   {
     "data/test-read-dwarf/test4.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test4.so.abi",
     "output/test-read-dwarf/test4.so.abi"
@@ -160,6 +175,7 @@
   {
     "data/test-read-dwarf/test4.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test4.so.hash.abi",
     "output/test-read-dwarf/test4.so.hash.abi"
@@ -167,6 +183,7 @@
   {
     "data/test-read-dwarf/test5.o",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test5.o.abi",
     "output/test-read-dwarf/test5.o.abi"
@@ -174,6 +191,7 @@
   {
     "data/test-read-dwarf/test5.o",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test5.o.hash.abi",
     "output/test-read-dwarf/test5.o.hash.abi"
@@ -181,6 +199,7 @@
   {
     "data/test-read-dwarf/test6.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test6.so.abi",
     "output/test-read-dwarf/test6.so.abi"
@@ -188,6 +207,7 @@
   {
     "data/test-read-dwarf/test6.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test6.so.hash.abi",
     "output/test-read-dwarf/test6.so.hash.abi"
@@ -195,6 +215,7 @@
   {
     "data/test-read-dwarf/test7.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test7.so.abi",
     "output/test-read-dwarf/test7.so.abi"
@@ -202,6 +223,7 @@
   {
     "data/test-read-dwarf/test7.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test7.so.hash.abi",
     "output/test-read-dwarf/test7.so.hash.abi"
@@ -209,6 +231,7 @@
   {
     "data/test-read-dwarf/test8-qualified-this-pointer.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test8-qualified-this-pointer.so.abi",
     "output/test-read-dwarf/test8-qualified-this-pointer.so.abi"
@@ -216,6 +239,7 @@
   {
     "data/test-read-dwarf/test8-qualified-this-pointer.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test8-qualified-this-pointer.so.hash.abi",
     "output/test-read-dwarf/test8-qualified-this-pointer.so.hash.abi"
@@ -223,6 +247,7 @@
   {
     "data/test-read-dwarf/test9-pr18818-clang.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test9-pr18818-clang.so.abi",
     "output/test-read-dwarf/test9-pr18818-clang.so.abi"
@@ -230,6 +255,7 @@
   {
     "data/test-read-dwarf/test10-pr18818-gcc.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test10-pr18818-gcc.so.abi",
     "output/test-read-dwarf/test10-pr18818-gcc.so.abi"
@@ -237,6 +263,7 @@
   {
     "data/test-read-dwarf/test11-pr18828.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test11-pr18828.so.abi",
     "output/test-read-dwarf/test11-pr18828.so.abi",
@@ -244,6 +271,7 @@
   {
     "data/test-read-dwarf/test12-pr18844.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test12-pr18844.so.abi",
     "output/test-read-dwarf/test12-pr18844.so.abi",
@@ -251,6 +279,7 @@
   {
     "data/test-read-dwarf/test13-pr18894.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test13-pr18894.so.abi",
     "output/test-read-dwarf/test13-pr18894.so.abi",
@@ -258,6 +287,7 @@
   {
     "data/test-read-dwarf/test14-pr18893.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test14-pr18893.so.abi",
     "output/test-read-dwarf/test14-pr18893.so.abi",
@@ -265,6 +295,7 @@
   {
     "data/test-read-dwarf/test15-pr18892.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test15-pr18892.so.abi",
     "output/test-read-dwarf/test15-pr18892.so.abi",
@@ -272,6 +303,7 @@
   {
     "data/test-read-dwarf/test16-pr18904.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test16-pr18904.so.abi",
     "output/test-read-dwarf/test16-pr18904.so.abi",
@@ -279,6 +311,7 @@
   {
     "data/test-read-dwarf/test17-pr19027.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test17-pr19027.so.abi",
     "output/test-read-dwarf/test17-pr19027.so.abi",
@@ -286,6 +319,7 @@
   {
     "data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi",
     "output/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi",
@@ -293,6 +327,7 @@
   {
     "data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi",
     "output/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi",
@@ -300,6 +335,7 @@
   {
     "data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi",
     "output/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi",
@@ -307,6 +343,7 @@
   {
     "data/test-read-dwarf/test21-pr19092.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test21-pr19092.so.abi",
     "output/test-read-dwarf/test21-pr19092.so.abi",
@@ -314,6 +351,7 @@
   {
     "data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi",
     "output/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi",
@@ -321,6 +359,7 @@
   {
     "data/test-read-dwarf/libtest23.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/libtest23.so.abi",
     "output/test-read-dwarf/libtest23.so.abi",
@@ -328,6 +367,7 @@
   {
     "data/test-read-dwarf/libtest24-drop-fns.so",
     "data/test-read-dwarf/test24-drop-fns-0.suppr",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/libtest24-drop-fns.so.abi",
     "output/test-read-dwarf/libtest24-drop-fns.so.abi",
@@ -335,6 +375,7 @@
   {
     "data/test-read-dwarf/libtest24-drop-fns.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/libtest24-drop-fns-2.so.abi",
     "output/test-read-dwarf/libtest24-drop-fns-2.so.abi",
@@ -342,6 +383,7 @@
   {
     "data/test-read-dwarf/PR22015-libboost_iostreams.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/PR22015-libboost_iostreams.so.abi",
     "output/test-read-dwarf/PR22015-libboost_iostreams.so.abi",
@@ -349,6 +391,7 @@
   {
     "data/test-read-dwarf/PR22122-libftdc.so",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/PR22122-libftdc.so.abi",
     "output/test-read-dwarf/PR22122-libftdc.so.abi",
@@ -356,6 +399,7 @@
   {
     "data/test-read-dwarf/PR24378-fn-is-not-scope.o",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/PR24378-fn-is-not-scope.abi",
     "output/test-read-dwarf/PR24378-fn-is-not-scope.abi",
@@ -364,6 +408,7 @@
   {
     "data/test-read-dwarf/PR25007-sdhci.ko",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/PR25007-sdhci.ko.abi",
     "output/test-read-dwarf/PR25007-sdhci.ko.abi",
@@ -373,6 +418,7 @@
   {
     "data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi",
     "output/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi",
@@ -381,6 +427,7 @@
   {
     "data/test-read-dwarf/test25-bogus-binary.elf",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     NULL,
     NULL,
@@ -388,6 +435,7 @@
   {
     "data/test-read-dwarf/test26-bogus-binary.elf",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     NULL,
     NULL,
@@ -395,6 +443,7 @@
   {
     "data/test-read-dwarf/test27-bogus-binary.elf",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     NULL,
     NULL,
@@ -402,6 +451,7 @@
   {
     "data/test-read-dwarf/PR26261/PR26261-exe",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/PR26261/PR26261-exe.abi",
     "output/test-read-dwarf/PR26261/PR26261-exe.abi",
@@ -409,6 +459,7 @@
   {
     "data/test-read-dwarf/test-PR26568-1.o",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test-PR26568-1.o.abi",
     "output/test-read-dwarf/test-PR26568-1.o.abi",
@@ -416,6 +467,7 @@
   {
     "data/test-read-dwarf/test-PR26568-2.o",
     "",
+    "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test-PR26568-2.o.abi",
     "output/test-read-dwarf/test-PR26568-2.o.abi",
@@ -423,12 +475,21 @@
   {
     "data/test-read-dwarf/test-libandroid.so",
     "",
+    "",
     HASH_TYPE_ID_STYLE,
     "data/test-read-dwarf/test-libandroid.so.abi",
     "output/test-read-dwarf/test-libandroid.so.abi",
   },
+  {
+    "data/test-read-dwarf/PR27700/test-PR27700.o",
+    "",
+    "data/test-read-dwarf/PR27700/pub-incdir",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-dwarf/PR27700/test-PR27700.abi",
+    "output/test-read-dwarf/PR27700/test-PR27700.abi",
+  },
   // This should be the last entry.
-  {NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
+  {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
 };
 
 using abigail::suppr::suppression_sptr;
@@ -448,6 +509,33 @@
   add_read_context_suppressions(read_ctxt, supprs);
 }
 
+/// Define what headers contain public types definitions.
+///
+/// This automatically generates suppression specifications from the
+/// set of header files present under a given directory.  Those
+/// specifications actually suppress types that are *not* defined in
+/// the headers found at a given directory.
+///
+/// @param read_ctxt the context used to read the ELF binary.
+///
+/// @param path the path to a directory where header files are to be
+/// found.
+static void
+set_suppressions_from_headers(read_context& read_ctxt, const string& path)
+{
+  vector<string> files;
+  suppression_sptr suppr =
+    abigail::tools_utils::gen_suppr_spec_from_headers(path, files);
+
+  if (suppr)
+    {
+      suppr->set_drops_artifact_from_ir(true);
+      suppressions_type supprs;
+      supprs.push_back(suppr);
+      add_read_context_suppressions(read_ctxt, supprs);
+    }
+}
+
 /// The task that peforms the tests.
 struct test_task : public abigail::workers::task
 {
@@ -477,7 +565,8 @@
   virtual void
   perform()
   {
-    string in_elf_path, in_abi_path, in_suppr_spec_path, out_abi_path;
+    string in_elf_path, in_abi_path, in_suppr_spec_path, in_public_headers_path,
+      out_abi_path;
     abigail::ir::environment_sptr env;
 
     in_elf_path = in_elf_base + spec.in_elf_path;
@@ -486,6 +575,11 @@
     else
       in_suppr_spec_path.clear();
 
+    if (spec.in_public_headers_path)
+      in_public_headers_path = spec.in_public_headers_path;
+    if (!in_public_headers_path.empty())
+      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
+
     env.reset(new abigail::ir::environment);
     abigail::dwarf_reader::status status =
     abigail::dwarf_reader::STATUS_UNKNOWN;
@@ -498,6 +592,9 @@
     if (!in_suppr_spec_path.empty())
       set_suppressions(*ctxt, in_suppr_spec_path);
 
+    if (!in_public_headers_path.empty())
+      set_suppressions_from_headers(*ctxt, in_public_headers_path);
+
     abigail::corpus_sptr corp = read_corpus_from_elf(*ctxt, status);
     // if there is no output and no input, assume that we do not care about the
     // actual read result, just that it succeeded.
@@ -541,7 +638,11 @@
     of.close();
 
     string abidw = string(get_build_dir()) + "/tools/abidw";
-    string cmd = abidw + " --abidiff " + in_elf_path;
+    string drop_private_types;
+    if (!in_public_headers_path.empty())
+      drop_private_types += "--headers-dir " + in_public_headers_path +
+	" --drop-private-types";
+    string cmd = abidw + " " + drop_private_types + " --abidiff " + in_elf_path;
     if (system(cmd.c_str()))
       {
 	error_message = string("ABIs differ:\n")