This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Re: may_alias attribute and type identity (PR c++/34935, PR c++/34936)


On Jan 24, 2008 11:41 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Thu, Jan 24, 2008 at 04:06:47PM +0100, Richard Guenther wrote:
> > On Jan 24, 2008 3:58 PM, Doug Gregor <doug.gregor@gmail.com> wrote:
> > The middle-end type system (useless_type_conversion_p) says that
> > pointers to int and pointers to int __attribute__((may_alias)) are
> > distinct (you can't use one in place of the other without changning
> > semantics) - because the pointed to types have different alias sets.
> >
> > Now, for rvalues that doesn't matter, so indeed a value of type
> > int and a value of type int __attribute__((may_alias)) can be used
> > in place of each other.  So I stand corrected and they should indeed
> > have the same canonical type.
>
> See also http://gcc.gnu.org/PR34936.  Is int __attribute__((may_alias))
> supposed to be mangled the same as int?  And if so, it should for cp/call.c
> purposes be treated the same as well.

I just started venturing down this rabbit hole when I saw your note.
Since we previously ignored the may_alias attribute, we ended up
treating "int" and its may_alias typedef as identical nodes; that also
seems like the right answer from the perspective of C++, because I
think we want these types to mangle the same, act identical in
overload resolution, etc. However, both the mangler (PR 34936) and the
structural type checking routines (PR 34935) are unprepared for
attribute-qualified typedefs like these, because they depend on the
TYPE_MAIN_VARIANT being equivalent to one the predefined type nodes
(which isn't the case with attribute-qualified typedefs).

The canonical type system gets this right: it sees the types as
equivalent, and always gives us a path from the typedef'd,
attribute-qualified versions of types back to the predefined type
nodes (which are the canonical versions, by design). So, I'm fixing
both PRs by using canonical types. With 34935, we end up just relying
on canonical types to compare INTEGER_TYPE, FIXED_POINT_TYPE, and
REAL_TYPE nodes, because there's no other way to do it without
fundamentally changing how attribute-qualified typedefs are
represented. With 34936, we just map the builtin type down to its
canonical form, which will be one of the predefined type nodes.

The attached patch fixes both PRs. Regression tests are still running
on i686-pc-linux-gnu, but assuming no problems crop up... okay for
mainline?

  - Doug

2008-01-24  Douglas Gregor  <doug.gregor@gmail.com>
            Jakub Jelinek  <jakub@redhat.com>
	
	PR c++/34935
	PR c++/34936
	* typeck.c (structural_comptypes): Handle comparisons of
	VOID_TYPE, BOOLEAN_TYPE, INTEGER_TYPE, FIXED_POINT_TYPE, and
	REAL_TYPE nodes.
	* mangle.c (write_builtin_type): Map down to the canonical type,
	which will be one of the predefined type nodes.

2008-01-24  Douglas Gregor  <doug.gregor@gmail.com>
            Jakub Jelinek  <jakub@redhat.com>
	
	PR c++/34935
	PR c++/34936
	* g++.dg/ext/alias-canon.C: New.
	* g++.dg/ext/alias-mangle.C: New.
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 131778)
+++ cp/typeck.c	(working copy)
@@ -976,6 +976,30 @@ structural_comptypes (tree t1, tree t2, 
   /* Compare the types.  Break out if they could be the same.  */
   switch (TREE_CODE (t1))
     {
+    case VOID_TYPE:
+    case BOOLEAN_TYPE:
+      /* All void and bool types are the same.  */
+      break;
+
+    case INTEGER_TYPE:
+    case FIXED_POINT_TYPE:
+    case REAL_TYPE:
+      /* With these nodes, we can't determine type equivalence by
+	 looking at what is stored in the nodes themselves, because
+	 two nodes might have different TYPE_MAIN_VARIANTs but still
+	 represent the same type.  For example, wchar_t and int could
+	 have the same properties (TYPE_PRECISION, TYPE_MIN_VALUE,
+	 TYPE_MAX_VALUE, etc.), but have different TYPE_MAIN_VARIANTs
+	 and are distinct types. On the other hand, int and the
+	 following typedef
+
+           typedef int INT __attribute((may_alias));
+
+	 have identical properties, different TYPE_MAIN_VARIANTs, but
+	 represent the same type.  The canonical type system keeps
+	 track of equivalence in this case, so we fall back on it.  */
+      return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
       if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 131778)
+++ cp/mangle.c	(working copy)
@@ -1768,6 +1768,9 @@ write_CV_qualifiers_for_type (const tree
 static void
 write_builtin_type (tree type)
 {
+  if (TYPE_CANONICAL (type))
+    type = TYPE_CANONICAL (type);
+
   switch (TREE_CODE (type))
     {
     case VOID_TYPE:
Index: testsuite/g++.dg/ext/alias-canon.C
===================================================================
--- testsuite/g++.dg/ext/alias-canon.C	(revision 0)
+++ testsuite/g++.dg/ext/alias-canon.C	(revision 0)
@@ -0,0 +1,41 @@
+// PR c++/34935
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "_Z1fi" } } */
+/* { dg-final { scan-assembler "_Z1fb" } } */
+/* { dg-final { scan-assembler "_Z1fd" } } */
+/* { dg-final { scan-assembler "_Z1ff" } } */
+/* { dg-final { scan-assembler "_Z1fw" } } */
+
+typedef int INT __attribute((may_alias));
+
+void f(int);
+void f(INT) { }
+
+typedef bool BOOL __attribute((may_alias));
+
+void f(bool);
+void f(BOOL) { }
+
+typedef float FLOAT __attribute((may_alias));
+
+void f(float);
+void f(FLOAT) { }
+
+typedef double DOUBLE __attribute((may_alias));
+
+void f(double);
+void f(DOUBLE) {}
+
+typedef wchar_t WCHAR_T __attribute((may_alias));
+
+void f(wchar_t);
+void f(WCHAR_T) {}
+
+void test()
+{
+  f(0);
+  f(true);
+  f(1.0f);
+  f(1.0);
+  f(L'f');
+}
Index: testsuite/g++.dg/ext/alias-mangle.C
===================================================================
--- testsuite/g++.dg/ext/alias-mangle.C	(revision 0)
+++ testsuite/g++.dg/ext/alias-mangle.C	(revision 0)
@@ -0,0 +1,11 @@
+// PR c++/34936
+// { dg-do compile }
+/* { dg-final { scan-assembler "_ZN1AIdEC1Ev" } } */
+typedef double X __attribute((may_alias)) ;
+
+template<typename> struct A
+{
+  A();
+};
+
+A<X> a;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]