Bug 26127 - abidw --annotate emits incomplete function types

When we get the qualified name of a pointer type, the result is cached
so that subsequent invocations of the getter yields a faster result.

When the pointed-to type is not yet fully constructed at the time of
the first invocation of the getter of the qualified name, what is
cached is the name of the pointer to a non-yet fully qualified type.

Then after the pointed-to type is fully constructed (and
canonicalized), the pointer type also becomes canonicalized (in that
order) and thus, the cache needs to be invalidated so that the
qualified name of the pointer to the fully qualified type is cached
again by a subsequent invocation of the getter.

The problem in this problem report is that the cache doesn't get
invalidated when the pointer type is canonicalized.

This patch fixes that.  A similar issue exists with reference and
qualified types so the patch addresses it for those types as well.

	* include/abg-ir.h (decl_base::clear_qualified_name): Declare new
	protected member function.
	({pointer_type_def, reference_type_def, qualified_type_def,
	function_type}::on_canonical_type_set): Declare virtual member
	functions.
	* src/abg-ir.cc (decl_base::clear_qualified_name): Define new
	protected member function.
	({pointer_type_def, reference_type_def, qualified_type_def,
	function_type}::on_canonical_type_set): Define virtual member
	functions.
	* tests/data/test-annotate/test17-pr19027.so.abi: Adjust.
	* tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	Likewise.
	* tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
diff --git a/include/abg-ir.h b/include/abg-ir.h
index ebcc4b8..d81de21 100644
--- a/include/abg-ir.h
+++ b/include/abg-ir.h
@@ -1392,6 +1392,9 @@
   peek_qualified_name() const;
 
   void
+  clear_qualified_name();
+
+  void
   set_qualified_name(const interned_string&) const;
 
   const interned_string&
@@ -2024,6 +2027,7 @@
 
 protected:
   string build_name(bool, bool internal = false) const;
+  virtual void on_canonical_type_set();
 
 public:
 
@@ -2126,6 +2130,9 @@
   // Forbidden.
   pointer_type_def();
 
+protected:
+  virtual void on_canonical_type_set();
+
 public:
 
   /// A hasher for instances of pointer_type_def
@@ -2180,6 +2187,9 @@
   // Forbidden.
   reference_type_def();
 
+protected:
+  virtual void on_canonical_type_set();
+
 public:
 
   /// Hasher for intances of reference_type_def.
@@ -3068,6 +3078,9 @@
   struct priv;
   typedef shared_ptr<priv> priv_sptr;
 
+protected:
+  virtual void on_canonical_type_set();
+
 public:
   /// Hasher for an instance of function_type
   struct hash;
diff --git a/src/abg-ir.cc b/src/abg-ir.cc
index 217d42d..da3716d 100644
--- a/src/abg-ir.cc
+++ b/src/abg-ir.cc
@@ -3535,6 +3535,15 @@
 decl_base::peek_qualified_name() const
 {return priv_->qualified_name_;}
 
+/// Clear the qualified name of this decl.
+///
+/// This is useful to ensure that the cache for the qualified name of
+/// the decl is refreshed right after type canonicalization, for
+/// instance.
+void
+decl_base::clear_qualified_name()
+{priv_->qualified_name_.clear();}
+
 /// Setter for the qualified name.
 ///
 /// @param n the new qualified name.
@@ -13105,6 +13114,17 @@
 				    fully_qualified, internal);
 }
 
+/// This function is automatically invoked whenever an instance of
+/// this type is canonicalized.
+///
+/// It's an overload of the virtual type_base::on_canonical_type_set.
+///
+/// We put here what is thus meant to be executed only at the point of
+/// type canonicalization.
+void
+qualified_type_def::on_canonical_type_set()
+{clear_qualified_name();}
+
 /// Constructor of the qualified_type_def
 ///
 /// @param type the underlying type
@@ -13502,6 +13522,17 @@
   {}
 }; //end struct pointer_type_def
 
+/// This function is automatically invoked whenever an instance of
+/// this type is canonicalized.
+///
+/// It's an overload of the virtual type_base::on_canonical_type_set.
+///
+/// We put here what is thus meant to be executed only at the point of
+/// type canonicalization.
+void
+pointer_type_def::on_canonical_type_set()
+{clear_qualified_name();}
+
 pointer_type_def::pointer_type_def(const type_base_sptr&	pointed_to,
 				   size_t			size_in_bits,
 				   size_t			align_in_bits,
@@ -13783,6 +13814,17 @@
 
 // <reference_type_def definitions>
 
+/// This function is automatically invoked whenever an instance of
+/// this type is canonicalized.
+///
+/// It's an overload of the virtual type_base::on_canonical_type_set.
+///
+/// We put here what is thus meant to be executed only at the point of
+/// type canonicalization.
+void
+reference_type_def::on_canonical_type_set()
+{clear_qualified_name();}
+
 reference_type_def::reference_type_def(const type_base_sptr	pointed_to,
 				       bool			lvalue,
 				       size_t			size_in_bits,
@@ -16232,6 +16274,20 @@
   }
 };// end struc function_type::priv
 
+/// This function is automatically invoked whenever an instance of
+/// this type is canonicalized.
+///
+/// It's an overload of the virtual type_base::on_canonical_type_set.
+///
+/// We put here what is thus meant to be executed only at the point of
+/// type canonicalization.
+void
+function_type::on_canonical_type_set()
+{
+  priv_->cached_name_.clear();
+  priv_->internal_cached_name_.clear();
+}
+
 /// The most straightforward constructor for the function_type class.
 ///
 /// @param return_type the return type of the function type.
diff --git a/tests/data/test-annotate/test17-pr19027.so.abi b/tests/data/test-annotate/test17-pr19027.so.abi
index 4937e36..42d5f81 100644
--- a/tests/data/test-annotate/test17-pr19027.so.abi
+++ b/tests/data/test-annotate/test17-pr19027.so.abi
@@ -36663,7 +36663,7 @@
         <var-decl name='normalization_preference' type-id='type-id-1939' visibility='default' filepath='/tmp/legendre/spack-stage/spack-stage-04g73E/harfbuzz-0.9.37/src/hb-ot-shape-complex-private.hh' line='114' column='1'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='448'>
-        <!-- bool ()* hb_ot_complex_shaper_t::decompose -->
+        <!-- bool (const hb_ot_shape_normalize_context_t*, typedef hb_codepoint_t, hb_codepoint_t*, hb_codepoint_t*)* hb_ot_complex_shaper_t::decompose -->
         <var-decl name='decompose' type-id='type-id-1940' visibility='default' filepath='/tmp/legendre/spack-stage/spack-stage-04g73E/harfbuzz-0.9.37/src/hb-ot-shape-complex-private.hh' line='123' column='1'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='512'>
@@ -36785,7 +36785,7 @@
         <var-decl name='unicode' type-id='type-id-86' visibility='default' filepath='/tmp/legendre/spack-stage/spack-stage-04g73E/harfbuzz-0.9.37/src/hb-ot-shape-normalize-private.hh' line='57' column='1'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='256'>
-        <!-- bool ()* hb_ot_shape_normalize_context_t::decompose -->
+        <!-- bool (const hb_ot_shape_normalize_context_t*, typedef hb_codepoint_t, hb_codepoint_t*, hb_codepoint_t*)* hb_ot_shape_normalize_context_t::decompose -->
         <var-decl name='decompose' type-id='type-id-1940' visibility='default' filepath='/tmp/legendre/spack-stage/spack-stage-04g73E/harfbuzz-0.9.37/src/hb-ot-shape-normalize-private.hh' line='61' column='1'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='320'>
@@ -36802,7 +36802,7 @@
       <enumerator name='HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE' value='3'/>
       <enumerator name='HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT' value='1'/>
     </enum-decl>
-    <!-- bool ()* -->
+    <!-- bool (const hb_ot_shape_normalize_context_t*, typedef hb_codepoint_t, hb_codepoint_t*, hb_codepoint_t*)* -->
     <pointer-type-def type-id='type-id-1949' size-in-bits='64' id='type-id-1940'/>
     <!-- bool (const hb_ot_shape_normalize_context_t*, typedef hb_codepoint_t, typedef hb_codepoint_t, hb_codepoint_t*)* -->
     <pointer-type-def type-id='type-id-1950' size-in-bits='64' id='type-id-1941'/>
diff --git a/tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi b/tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi
index 0f42c9c..d5ab3e3 100644
--- a/tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi
+++ b/tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi
@@ -5095,11 +5095,11 @@
           </function-decl>
         </member-function>
         <member-function access='public'>
-          <!-- std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::operator<<(void ()*) -->
+          <!-- std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (std::basic_ostream<char, std::char_traits<char> >&)*) -->
           <function-decl name='operator&lt;&lt;' mangled-name='_ZNSolsEPFRSoS_E' filepath='/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream' line='108' column='1' visibility='default' binding='global' size-in-bits='64'>
             <!-- implicit parameter of type 'std::basic_ostream<char, std::char_traits<char> >*' -->
             <parameter type-id='type-id-215' is-artificial='yes'/>
-            <!-- parameter of type 'void ()*' -->
+            <!-- parameter of type 'std::basic_ostream<char, std::char_traits<char> >& (std::basic_ostream<char, std::char_traits<char> >&)*' -->
             <parameter type-id='type-id-276'/>
             <!-- std::basic_ostream<char, std::char_traits<char> >& -->
             <return type-id='type-id-214'/>
@@ -8298,7 +8298,7 @@
     <qualified-type-def type-id='type-id-65' const='yes' id='type-id-307'/>
     <!-- const vtkWeakPointer<vtkImageDataLIC2D>* -->
     <pointer-type-def type-id='type-id-307' size-in-bits='64' id='type-id-300'/>
-    <!-- void ()* -->
+    <!-- std::basic_ostream<char, std::char_traits<char> >& (std::basic_ostream<char, std::char_traits<char> >&)* -->
     <pointer-type-def type-id='type-id-308' size-in-bits='64' id='type-id-276'/>
     <!-- vtkImageDataLIC2D& -->
     <reference-type-def kind='lvalue' type-id='type-id-108' size-in-bits='64' id='type-id-301'/>
diff --git a/tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi b/tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi
index 14178e8..dc009c8 100644
--- a/tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi
+++ b/tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi
@@ -6555,7 +6555,7 @@
     <pointer-type-def type-id='type-id-260' size-in-bits='64' id='type-id-339'/>
     <!-- std::basic_ostream<char, std::char_traits<char> >& -->
     <reference-type-def kind='lvalue' type-id='type-id-340' size-in-bits='64' id='type-id-341'/>
-    <!-- void ()* -->
+    <!-- std::basic_ostream<char, std::char_traits<char> >& (std::basic_ostream<char, std::char_traits<char> >&)* -->
     <pointer-type-def type-id='type-id-342' size-in-bits='64' id='type-id-343'/>
     <!-- std::basic_ostream<char, std::char_traits<char> >* -->
     <pointer-type-def type-id='type-id-340' size-in-bits='64' id='type-id-344'/>
@@ -7693,11 +7693,11 @@
       <!-- struct std::basic_ostream<char, std::char_traits<char> > -->
       <class-decl name='basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;' is-struct='yes' visibility='default' is-declaration-only='yes' id='type-id-340'>
         <member-function access='public'>
-          <!-- std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::operator<<(void ()*) -->
+          <!-- std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (std::basic_ostream<char, std::char_traits<char> >&)*) -->
           <function-decl name='operator&lt;&lt;' mangled-name='_ZNSolsEPFRSoS_E' filepath='/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream' line='108' column='1' visibility='default' binding='global' size-in-bits='64'>
             <!-- implicit parameter of type 'std::basic_ostream<char, std::char_traits<char> >*' -->
             <parameter type-id='type-id-344' is-artificial='yes'/>
-            <!-- parameter of type 'void ()*' -->
+            <!-- parameter of type 'std::basic_ostream<char, std::char_traits<char> >& (std::basic_ostream<char, std::char_traits<char> >&)*' -->
             <parameter type-id='type-id-343'/>
             <!-- std::basic_ostream<char, std::char_traits<char> >& -->
             <return type-id='type-id-341'/>