Bug PR26739 - Handle qualified typedef array types

Message ID 878sbra8mj.fsf@redhat.com
State New
Headers
Series Bug PR26739 - Handle qualified typedef array types |

Commit Message

Dodji Seketeli Oct. 27, 2020, 5:20 p.m. UTC
  Hello,

CV-qualifiers of a typedef of an array type apply to the elements of
the array.  So this can be transformed into a typedef of array type
which element type is similarly CV-qualified.

That transformation helps avoiding spurious changes that might occur
when comparing the latter form against the former even though both are
equivalent.

This patch performs that transformation, just like we already do for
CV-qualified array types which are transformed into an array of
similarly CV-qualified elements.

	* include/abg-fwd.h (is_typedef_of_array): Declare new function.
	(peel_qualified_or_typedef_type): Declare new overload.
	* src/abg-dwarf-reader.cc (maybe_strip_qualification): Handle
	qualified typedef of arrays.
	* src/abg-ir.cc (peel_qualified_or_typedef_type): Define new
	overload for type_base_sptr.
	* tests/data/test-diff-filter/test-PR26739-report-0.txt: New
	reference test output.
	* tests/data/test-diff-filter/test-PR26739-v{0,1}.c: Source code
	of new binary test input.
	* tests/data/test-diff-filter/test-PR26739-v{0,1}.o: New binary
	test inputs.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/test-diff-filter.cc (in_out_specs): Add the test inputs
	above to this harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 include/abg-fwd.h                             |   6 ++
 src/abg-dwarf-reader.cc                       |  27 +++++++++
 src/abg-ir.cc                                 |  57 ++++++++++++++++++
 tests/data/Makefile.am                        |   5 ++
 .../test-PR26739-report-0.txt                 |   3 +
 tests/data/test-diff-filter/test-PR26739-v0.c |   8 +++
 tests/data/test-diff-filter/test-PR26739-v0.o | Bin 0 -> 2976 bytes
 tests/data/test-diff-filter/test-PR26739-v1.c |  12 ++++
 tests/data/test-diff-filter/test-PR26739-v1.o | Bin 0 -> 2920 bytes
 tests/test-diff-filter.cc                     |   7 +++
 10 files changed, 125 insertions(+)
 create mode 100644 tests/data/test-diff-filter/test-PR26739-report-0.txt
 create mode 100644 tests/data/test-diff-filter/test-PR26739-v0.c
 create mode 100644 tests/data/test-diff-filter/test-PR26739-v0.o
 create mode 100644 tests/data/test-diff-filter/test-PR26739-v1.c
 create mode 100644 tests/data/test-diff-filter/test-PR26739-v1.o
  

Patch

diff --git a/include/abg-fwd.h b/include/abg-fwd.h
index 4b09929c..36c73f7a 100644
--- a/include/abg-fwd.h
+++ b/include/abg-fwd.h
@@ -708,6 +708,9 @@  is_array_of_qualified_element(type_base_sptr&);
 qualified_type_def_sptr
 is_array_of_qualified_element(const array_type_def_sptr&);
 
+array_type_def_sptr
+is_typedef_of_array(const type_base_sptr&);
+
 void
 set_data_member_offset(var_decl_sptr, uint64_t);
 
@@ -848,6 +851,9 @@  peel_qualified_type(const type_base_sptr&);
 type_base*
 peel_qualified_or_typedef_type(const type_base* type);
 
+type_base_sptr
+peel_qualified_or_typedef_type(const type_base_sptr &type);
+
 type_base_sptr
 peel_typedef_pointer_or_reference_type(const type_base_sptr);
 
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 7257052e..45f3cf62 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -14342,6 +14342,33 @@  maybe_strip_qualification(const qualified_type_def_sptr t,
 	// delayed until after all editing is done.
 	ABG_ASSERT_NOT_REACHED;
     }
+  else if (array_type_def_sptr array = is_typedef_of_array(u))
+    {
+      // We should not be editing types that are already canonicalized.
+      ABG_ASSERT(!array->get_canonical_type());
+      type_base_sptr element_type = array->get_element_type();
+
+      if (qualified_type_def_sptr qualified = is_qualified_type(element_type))
+	{
+	  // We should not be editing types that are already canonicalized.
+	  ABG_ASSERT(!qualified->get_canonical_type());
+	  qualified_type_def::CV quals = qualified->get_cv_quals();
+	  quals |= t->get_cv_quals();
+	  qualified->set_cv_quals(quals);
+	  result = is_decl(u);
+	}
+      else
+	{
+	  qualified_type_def_sptr qual_type
+	    (new qualified_type_def(element_type,
+				    t->get_cv_quals(),
+				    t->get_location()));
+	  add_decl_to_scope(qual_type, is_decl(element_type)->get_scope());
+	  array->set_element_type(qual_type);
+	  ctxt.schedule_type_for_late_canonicalization(is_type(qual_type));
+	  result = is_decl(u);
+	}
+    }
 
   return result;
 }
diff --git a/src/abg-ir.cc b/src/abg-ir.cc
index 8c04797f..5e5937a5 100644
--- a/src/abg-ir.cc
+++ b/src/abg-ir.cc
@@ -5813,6 +5813,35 @@  peel_qualified_or_typedef_type(const type_base* type)
   return const_cast<type_base*>(type);
 }
 
+/// Return the leaf underlying type of a qualified or typedef type.
+///
+/// If the underlying type is itself a qualified or typedef type, then
+/// recursively return the first underlying type of that qualified or
+/// typedef type to return the first underlying type that is not a
+/// qualified or typedef type.
+///
+/// If the underlying type is NOT a qualified nor a typedef type, then
+/// just return that underlying type.
+///
+/// @param type the qualified or typedef type to consider.
+///
+/// @return the leaf underlying type.
+type_base_sptr
+peel_qualified_or_typedef_type(const type_base_sptr &t)
+{
+  type_base_sptr type = t;
+  while (is_typedef(type) || is_qualified_type(type))
+    {
+      if (typedef_decl_sptr t = is_typedef(type))
+	type = peel_typedef_type(t);
+
+      if (qualified_type_def_sptr t = is_qualified_type(type))
+	type = peel_qualified_type(t);
+    }
+
+  return type;
+}
+
 /// Return the leaf underlying or pointed-to type node of a @ref
 /// typedef_decl, @ref pointer_type_def or @ref reference_type_def
 /// node.
@@ -8646,6 +8675,34 @@  is_array_of_qualified_element(type_base_sptr& type)
   return array_type_def_sptr();
 }
 
+/// Test if a type is a typedef of an array.
+///
+/// Note that the function looks through qualified and typedefs types
+/// of the underlying type of the current typedef.  In other words, if
+/// we are looking at a typedef of a CV-qualified array, or at a
+/// typedef of a CV-qualified typedef of an array, this function will
+/// still return TRUE.
+///
+/// @param t the type to consider.
+///
+/// @return true if t is a typedef which underlying type is an array.
+/// That array might be either cv-qualified array or a typedef'ed
+/// array, or a combination of both.
+array_type_def_sptr
+is_typedef_of_array(const type_base_sptr& t)
+{
+  array_type_def_sptr result;
+
+  if (typedef_decl_sptr typdef = is_typedef(t))
+    {
+      type_base_sptr u =
+	peel_qualified_or_typedef_type(typdef->get_underlying_type());
+      result = is_array_type(u);
+    }
+
+  return result;
+}
+
 /// Test if a type is an array_type_def::subrange_type.
 ///
 /// @param type the type to consider.
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 40a575fa..db9a8e36 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -888,6 +888,11 @@  test-diff-filter/test-PR26309-v1.c           \
 test-diff-filter/test-PR26309-v0.o           \
 test-diff-filter/test-PR26309-v1.o           \
 test-diff-filter/test-PR26309-report-0.txt   \
+test-diff-filter/test-PR26739-v0.c           \
+test-diff-filter/test-PR26739-v1.c           \
+test-diff-filter/test-PR26739-v0.o           \
+test-diff-filter/test-PR26739-v1.o           \
+test-diff-filter/test-PR26739-report-0.txt   \
 \
 test-diff-suppr/test0-type-suppr-v0.cc	\
 test-diff-suppr/test0-type-suppr-v1.cc	\
diff --git a/tests/data/test-diff-filter/test-PR26739-report-0.txt b/tests/data/test-diff-filter/test-PR26739-report-0.txt
new file mode 100644
index 00000000..9666a8fd
--- /dev/null
+++ b/tests/data/test-diff-filter/test-PR26739-report-0.txt
@@ -0,0 +1,3 @@ 
+Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
diff --git a/tests/data/test-diff-filter/test-PR26739-v0.c b/tests/data/test-diff-filter/test-PR26739-v0.c
new file mode 100644
index 00000000..e9148ac4
--- /dev/null
+++ b/tests/data/test-diff-filter/test-PR26739-v0.c
@@ -0,0 +1,8 @@ 
+typedef const int immutable[7];
+typedef immutable monster;
+
+struct A {
+  monster q;
+};
+
+void fun(struct A * a) { (void) a; }
diff --git a/tests/data/test-diff-filter/test-PR26739-v0.o b/tests/data/test-diff-filter/test-PR26739-v0.o
new file mode 100644
index 0000000000000000000000000000000000000000..5a4ae08f964055b0a411d330d9f3ba3d727a7b89
GIT binary patch
literal 2976
zcmbVO&2Jk;6o2Ej<4ra(NlYOoJ#0mxjnrM+X`4DlDJ~IBA}SO`RB)h**7n$5@UDZs
zt`ZPJLKUbIhgL#DNZhy~4oDohBJmG!<iLRo636z2!~x#hopC1PMXmZI&%F7)@0oeC
z{^a$WH!_TYBnH>ucqLJQKc<fPdd$|L2#auQ``(}1_dfpn{_S6WL^vCZ%-F+h%qxSX
z@EPJ6E3V^Yyp6*S{<1VoLC(zM3{%;hA4ZVhMLto_6dmOA@8V!yhtn);-bHr$17JC;
ziyXjAdlUjQ$H~f&?3*7@YI!I-MO@}V7iP_XOxOZ@sZg|x!g67OE#~K+N9l856s}sY
zSnJkK5%Xhgr^t}Wo`IcW8GYu?f@NJp8_ZI$CMNbWiZQh!Gfc}$?8$6;4h&PetD*Uf
z%U&%>=v;}y)|b9|twhRJPEpP*0n9#wvB)o6pu{O<z+ei=A{8iR-@?&=8jg(pQ<%ds
zK4?4~2D^K!YgaC=JHaUO!pMn^4tR^V9d9u3j+{Fcw;6lLEx~jW5tpUh*-tYDdg=AU
zjy(#8ekbHDo6acchr@^uVC&6W_Ga~pU9GsQZq;6`tX8U(%4Pff9x85okq|hSS8OMU
zMj_wm@Q@GuCN8}}v%7IvTXWVf*-qyP67&N~zR}}Q?)C#-ZuML5`Q?rum3w}}Yxo_{
z@0CTJ<%kcXVY%f+Ud%czzuk7)evh(-t<BA=_IXTx<q0y6HwK<fCSV`#0Xv*$%d>g&
zKJM&k#OX&ApUd^a{AZcXxv3kdkie-Ubxal>{hKDlJx_!2Y{zGFLT;cWjSSJAy3D|y
zOCtl~KAaF4Fg<}0U?de!$PAd9z!H7zpA<4+;^}}FQEyS%hw+_%{6(fGVO-%1`cbQu
zkqD=%UcevGLNbBGxmcgl@CRaD5;L8YdMYc5zIy(yf>Yej#rmd(izVFF@I|ryLd<$x
zStI426FM}_3trdX`XAgDIMt-q1@7=D!0y928YFX9auGj_z@=UTw=o=oJK#OfZSlsa
zv+sxPKFVU=YcvM@&Iz$M@WKv1Y0~pUE=@25xXpeLaC~*#upe<3+twLIUh{q7h<Eqf
z122#VCh~vUX&DV^ujGD8KXt*3@1a<eu1aTcL73i=Z>UNNuiKwP8Qq(wwXdSB?vujF
z_&?D?Azk+Z%IKqBS9FN|EBVsHLxI!1B1qnG{BXszfurt|1Q`K-7i%34y6!HDbd0pW
z7hvVsH0E?&sxvMB-$YYLd&-|)J3apvV!BU+;CBJOLkop;-F=j$#g~6k<UUb+dI$9Q
z2Z)hRnJ2O_T@uass|3U><IDLY#MA7v;zE@lV}DoJYie*&zmP&f#+CYC3;Ppq2Vym0
zPybF-lJ!gMOJvga&lU}-?jL<kq`kx`A3ZktJ`nMDMZ)yn(^pEjr!z?_^=C>7iTYC|
Ty?*kWW?vKef2$fJuiO6zTQuNz

literal 0
HcmV?d00001

diff --git a/tests/data/test-diff-filter/test-PR26739-v1.c b/tests/data/test-diff-filter/test-PR26739-v1.c
new file mode 100644
index 00000000..5c31e40c
--- /dev/null
+++ b/tests/data/test-diff-filter/test-PR26739-v1.c
@@ -0,0 +1,12 @@ 
+typedef int plain[7];
+typedef const plain monster;
+
+struct A {
+  monster q;
+};
+
+void fun(struct A * a) {
+  (void) a;
+  // assignment to read-only location
+  // a->q[0] = 0;
+}
diff --git a/tests/data/test-diff-filter/test-PR26739-v1.o b/tests/data/test-diff-filter/test-PR26739-v1.o
new file mode 100644
index 0000000000000000000000000000000000000000..9966762568f70b7ac8f631b4c8ba904f7557a9c5
GIT binary patch
literal 2920
zcmbtV-D@0G6hC)oH#^BBYmzmZHGP;;Z5wcAcB4(xYU<W#lh7g|wA2SB%<kUZ9o?O+
zv$G{p#22abt%4w;U{Mh9-w;Ib#Yg{vLVfI;&<8zd=HBhi%}9$Lm^tVE&gcC&_kQx`
zl}kCsKoWxs@Mt7afFCCw$@N66LmB4b+ScuRTem;{>(0ABe}`~BQJG1E=|on3mLlig
zz`;6x2K^==Zx%^g$QObz#xWAhEjY-Em+@y_gkvmk4pE%^09e7gjuOCBdlUjQ$F<1}
z?3-^<Yx$^KASw5G7pBd3$c4?Z7fNNzC@q!d*nDyJS=2JNU1nvh<v47YJq(h69xUqu
z8ev63G_lHOz$l%!Ua`(u+h|=piPl(JnHi>Kr8q^IoB_j>W@{L2%4M%rBy_4mY3qw$
zzFr|?tDqR?76GQ8!qgNOUZldQWWd}C$w?|uB3{M60c-eY>|tpJ|H;1MUNG3%U0FT*
z(mAI;iv2Kl;)5H!#oLY_MgD<vv*tFF2!%zMOf%xJQed}o21e-(!j3%(he0RgEt|Hd
zKM030kDegv=3Ce7joMkeR&`h0n!Qq8sn)91Gxq6S47KIQLgAcQww-=F3i*16hdc_J
zIP{}tcYS|t)meSnb~@m72Yv3f2Cer3uM@;xFKGCUpyLNUPt4AX`7j=OEkE`X(P;(k
zw$l!JR4Z(5Y@D}GV?oPLPz^ktEC?>$hr7V`XW7zp(Y%98c?@y-h?0%CSem_++nAZS
zga#>``KOM^!-K!Gl(@)QFmC2}GY;tu)MSw%+E3RRX+P;OMoD@u1D`yC5n!Y<KB6;V
z<_MPBWB+830Y|O|IDvNa$~ue>`QuM6-2vknPGOw!b%3(WL^#drRs4wNQU(%#PK*~c
z{4+7G2u?et?#i-aukL?c!PV8gqT%ym{E^^#d^s1Yvmk7U%?eq!-~1Qc7C6<e)(`IR
zpdb4U<Z+bpu9RZFAA?Kn1a4zE1UKS6-)-^6sIwP@?E&f%*>5x=e)EvpkNmL154-e&
zkV_X#0d8~9?{mCP+;9+c7dz7##(wjC5r}v9+L7PqqVWI8me8NpO0K62R~N$gyooW{
zs&pI&gz24kSv68*-TxHo=zRQF{~G%0F)5wQ{{sya(rxK6p~tzd*pT>Z`eMT$0;h9D
zkUY!yA|*txv>uZb4-zfFPl8LP+wP!3$H?|;0am4>;JPi%Gpqi)qA8?5)lavYUVjTQ
zJtji%n*iUYfkL|N9_q64|1R>&b)x*#?|S|lh*3;gCyEK35Y70D1O%7)C8zr#%l}W|
z?>)x<Q{k_f!J>X3g@Mc~?Y|QKhwcu<r2m>U6kN_<!e5|}wSM<A){kBd=`Yun>d|vk
r>>W}6jwqP!b$X3-f7+9*sotfckf=XZ(&tZcv;5_S^1bSevhM#6w{_d%

literal 0
HcmV?d00001

diff --git a/tests/test-diff-filter.cc b/tests/test-diff-filter.cc
index b3b1e91b..8d90b13e 100644
--- a/tests/test-diff-filter.cc
+++ b/tests/test-diff-filter.cc
@@ -773,6 +773,13 @@  InOutSpec in_out_specs[] =
    "data/test-diff-filter/test-PR26309-report-0.txt",
    "output/test-diff-filter/test-PR26309-report-0.txt",
   },
+  {
+   "data/test-diff-filter/test-PR26739-v0.o",
+   "data/test-diff-filter/test-PR26739-v1.o",
+   "--no-default-suppression",
+   "data/test-diff-filter/test-PR26739-report-0.txt",
+   "output/test-diff-filter/test-PR26739-report-0.txt",
+  },
   // This should be the last entry
   {NULL, NULL, NULL, NULL, NULL}
 };