Patchwork fix c++/44473, mangling for decimal classes

login
register
mail settings
Submitter Janis Johnson
Date Dec. 7, 2010, 9:58 p.m.
Message ID <AANLkTimjFaBT-_atVDL0pvMOakm8ZZoZmHqapCjbV3Z6@mail.gmail.com>
Download mbox | patch
Permalink /patch/74603/
State New
Headers show

Comments

Janis Johnson - Dec. 7, 2010, 9:58 p.m.
This fix to the C++ compiler fixes bug PR c++/44473. I had originally
assumed that the failure had something to do with templates and didn't
get far debugging it on my EeePC. I recently acquired a computer with
a screen large enough for development work and discovered that it was
just a simple bug that I had introduced in the mangler.

The decimalxx classes in std::decimal are mangled the same as decimal
floating point scalars from C, and the special-casing in the mangler
prevented CV qualifiers from being part of the mangled name. One of
the new tests is minimized from the submitter's testcase, one just
checks that the const qualifier appears, and the others, based on
existing tests for other types, check other basic mangling that wasn't
checked before for the decimal classses.

Tested with c,c++ bootstrap and testsuite on i686-pc-linux.gnu.
OK for trunk and 4.5?
2010-12-07  Janis Johnson  <janis.marie.johnson@gmail.com>

gcc/cp
	PR c++/44473
	* mangle.c (write_type): Handle CV qualifiers for decimal classes.

gcc/testsuite
	PR c++/44473
	* g++.dg/dfp/44473-1.C: New test.
	* g++.dg/dfp/44473-2.C: New test.
	* g++.dg/dfp/mangle-1.C: New test.
	* g++.dg/dfp/mangle-2.C: New test.
	* g++.dg/dfp/mangle-3.C: New test.
	* g++.dg/dfp/mangle-4.C: New test.
	* g++.dg/dfp/mangle-5.C: New test.
Paolo Carlini - Dec. 7, 2010, 10:15 p.m.
Il 07/12/10 22.58, Janis Johnson ha scritto:
> Tested with c,c++ bootstrap and testsuite on i686-pc-linux.gnu.
> OK for trunk and 4.5?
Many thanks Janis for working on this. Hopefully Jason and the C++ 
front-end maintainers will review it soon.

Paolo.
Jason Merrill - Dec. 15, 2010, 4:51 p.m.
OK.

Jason

Patch

Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 167519)
+++ cp/mangle.c	(working copy)
@@ -1787,11 +1787,6 @@  write_type (tree type)
   if (find_substitution (type))
     return;
 
-  /* According to the C++ ABI, some library classes are passed the
-     same as the scalar type of their single member and use the same
-     mangling.  */
-  if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
-    type = TREE_TYPE (first_field (type));
 
   if (write_CV_qualifiers_for_type (type) > 0)
     /* If TYPE was CV-qualified, we just wrote the qualifiers; now
@@ -1811,6 +1806,12 @@  write_type (tree type)
       /* See through any typedefs.  */
       type = TYPE_MAIN_VARIANT (type);
 
+      /* According to the C++ ABI, some library classes are passed the
+	 same as the scalar type of their single member and use the same
+	 mangling.  */
+      if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
+	type = TREE_TYPE (first_field (type));
+
       if (TYPE_PTRMEM_P (type))
 	write_pointer_to_member_type (type);
       else
Index: testsuite/g++.dg/dfp/44473-1.C
===================================================================
--- testsuite/g++.dg/dfp/44473-1.C	(revision 0)
+++ testsuite/g++.dg/dfp/44473-1.C	(revision 0)
@@ -0,0 +1,122 @@ 
+/* { dg-do assemble } */
+
+/* Minimized from the testcase in PR c++/44473; mangling of decimal types
+   did not include CV qualifiers. */
+
+namespace std
+{
+  namespace decimal
+  {
+    class decimal32
+    {
+    public:
+      typedef float __decfloat32 __attribute__ ((mode (SD)));
+      explicit decimal32 (float __r):__val (__r) {}
+    private:
+      __decfloat32 __val;
+    };
+  };
+
+  template <typename _BI1, typename _BI2>
+  _BI2 copy_backward (_BI1 __first, _BI2 __result);
+}
+
+namespace __gnu_cxx
+{
+  template <typename _Iterator, typename _Container>
+  class __normal_iterator
+  {
+  public:
+    explicit __normal_iterator (const _Iterator & __i) {}
+    const _Iterator & base () const {}
+  };
+
+  template <typename _IteratorL, typename _IteratorR, typename _Container>
+  bool operator== (const __normal_iterator <_IteratorL, _Container> &__lhs,
+		   const __normal_iterator <_IteratorR, _Container> &__rhs)
+  {
+    return __lhs.base () == __rhs.base ();
+  }
+
+  template <typename _Tp>
+  class new_allocator
+  {
+  public:
+    typedef _Tp *pointer;
+    typedef const _Tp *const_pointer;
+    template <typename _Tp1>
+    struct rebind
+    {
+      typedef new_allocator <_Tp1> other;
+    };
+  };
+}
+
+namespace std
+{
+  template <typename _Tp>
+  class allocator:public __gnu_cxx::new_allocator <_Tp> {};
+
+  template <typename _Tp, typename _Alloc>
+  struct _Vector_base
+  {
+    typedef typename _Alloc::template rebind <_Tp>::other _Tp_alloc_type;
+    struct _Vector_impl:public _Tp_alloc_type
+    {
+      typename _Tp_alloc_type::pointer _M_finish;
+    };
+  public:  _Vector_impl _M_impl;
+  };
+
+  template <typename _Tp, typename _Alloc = std::allocator <_Tp> >
+  class vector:protected _Vector_base <_Tp, _Alloc>
+  {
+    typedef _Vector_base <_Tp, _Alloc> _Base;
+    typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
+  public:
+    typedef _Tp value_type;
+    typedef typename _Tp_alloc_type::pointer pointer;
+    typedef typename _Tp_alloc_type::const_pointer const_pointer;
+    typedef __gnu_cxx::__normal_iterator <pointer, vector> iterator;
+    typedef __gnu_cxx::__normal_iterator <const_pointer, vector>
+      const_iterator;
+    const_iterator begin () const;
+    iterator end ()
+    {
+      return iterator (this->_M_impl._M_finish);
+    }
+    const_iterator end () const
+    {
+      return const_iterator (this->_M_impl._M_finish);
+    }
+    bool empty () const
+    {
+      return begin () == end ();
+    }
+    void push_back (const value_type & __x)
+    {
+      _M_insert_aux (end ());
+    }
+    void _M_insert_aux (iterator __position);
+  };
+
+  template <typename _Tp, typename _Alloc>
+  void vector <_Tp, _Alloc>::_M_insert_aux (iterator __position)
+  {
+    std::copy_backward (__position.base (), this->_M_impl._M_finish - 1);
+  }
+}
+
+std::vector <std::decimal::decimal32> vec;
+
+int
+foo ()
+{
+  return (vec.empty ()) ? 1 : 0;
+}
+
+bool
+bar ()
+{
+  vec.push_back (std::decimal::decimal32 (0));
+}
Index: testsuite/g++.dg/dfp/44473-2.C
===================================================================
--- testsuite/g++.dg/dfp/44473-2.C	(revision 0)
+++ testsuite/g++.dg/dfp/44473-2.C	(revision 0)
@@ -0,0 +1,25 @@ 
+// { dg-do compile }
+
+// Mangling of classes from std::decimal are special-cased.
+
+namespace std {
+  namespace decimal {
+    class decimal64 {
+      public:
+	typedef float __decfloat64 __attribute__ ((mode (DD)));
+	explicit decimal64 (int __r):__val (__r) {}
+      private:
+	__decfloat64 __val;
+    };
+  }
+}
+
+int bar (const std::decimal::decimal64 & x) { }
+
+int foo ()
+{
+  std::decimal::decimal64 x(0);
+  bar (x);
+}
+
+// { dg-final { scan-assembler "_Z3barRKDd:" } }
Index: testsuite/g++.dg/dfp/mangle-1.C
===================================================================
--- testsuite/g++.dg/dfp/mangle-1.C	(revision 0)
+++ testsuite/g++.dg/dfp/mangle-1.C	(revision 0)
@@ -0,0 +1,40 @@ 
+// { dg-do compile }
+
+// Mangling of classes from std::decimal are special-cased.
+// Derived from g++.dg/abi/mangle13.C.
+
+namespace std {
+  namespace decimal {
+    class decimal64 {
+      public:
+	typedef float __decfloat64 __attribute__ ((mode (DD)));
+	explicit decimal64 (float __r):__val (__r) {}
+      private:
+	__decfloat64 __val;
+    };
+  }
+}
+
+struct A {
+  template <typename T> std::decimal::decimal64 f ();
+  std::decimal::decimal64 operator+();
+  operator std::decimal::decimal64 ();
+  template <typename T>
+  std::decimal::decimal64 operator-();
+};
+
+typedef std::decimal::decimal64 (A::*P)();
+
+template <P> struct S {};
+
+template <typename T> void g (S<&T::template f<std::decimal::decimal64> >) {}
+template <typename T> void g (S<&T::operator+ >) {}
+template <typename T> void g (S<&T::operator std::decimal::decimal64>) {}
+template <typename T> void g (S<&T::template operator- <std::decimal::decimal64> >) {}
+
+template void g<A> (S<&A::f<std::decimal::decimal64> >);
+template void g<A> (S<&A::operator+>);
+template void g<A> (S<&A::operator std::decimal::decimal64>);
+
+// { dg-final { scan-assembler "\n?_Z1gI1AEv1SIXadsrT_1fIDdEEE\[: \t\n\]" } }
+// { dg-final { scan-assembler "\n?_Z1gI1AEv1SIXadsrT_plEE\[: \t\n\]" } }
Index: testsuite/g++.dg/dfp/mangle-2.C
===================================================================
--- testsuite/g++.dg/dfp/mangle-2.C	(revision 0)
+++ testsuite/g++.dg/dfp/mangle-2.C	(revision 0)
@@ -0,0 +1,28 @@ 
+// { dg-do compile }
+
+// Mangling of classes from std::decimal are special-cased.
+// Derived from g++.dg/abi/mangle15.C.
+
+namespace std {
+  namespace decimal {
+    class decimal64 {
+      public:
+	typedef float __decfloat64 __attribute__ ((mode (DD)));
+	explicit decimal64 (float __r):__val (__r) {}
+      private:
+	__decfloat64 __val;
+    };
+  }
+}
+
+struct A {
+  template <typename T> std::decimal::decimal64 f ();
+};
+
+typedef std::decimal::decimal64 (A::*P)();
+
+template <P> struct S {};
+
+void g (S<&A::f<std::decimal::decimal64> >) {}
+
+// { dg-final { scan-assembler "\n?_Z1g1SIXadL_ZN1A1fIDdEEDdvEEE\[: \t\n\]" } }
Index: testsuite/g++.dg/dfp/mangle-3.C
===================================================================
--- testsuite/g++.dg/dfp/mangle-3.C	(revision 0)
+++ testsuite/g++.dg/dfp/mangle-3.C	(revision 0)
@@ -0,0 +1,28 @@ 
+// { dg-do compile }
+
+// Mangling of classes from std::decimal are special-cased.
+// Derived from g++.dg/abi/mangle20-1.C.
+
+namespace std {
+  namespace decimal {
+    class decimal64 {
+      public:
+	typedef float __decfloat64 __attribute__ ((mode (DD)));
+	explicit decimal64 (int __r):__val (__r) {}
+      private:
+	__decfloat64 __val;
+    };
+  }
+}
+
+template <int I> void f(std::decimal::decimal64 (*)[2]) {}
+template <int I> void g(std::decimal::decimal64 (*)[I+2]) {}
+
+static const std::decimal::decimal64 I(1);
+static const std::decimal::decimal64 J(2);
+
+template void f<1>(std::decimal::decimal64 (*)[2]);
+template void g<1>(std::decimal::decimal64 (*)[3]);
+
+//  { dg-final { scan-assembler "\n_?_Z1fILi1EEvPA2_Dd\[: \t\n\]" } }
+//  { dg-final { scan-assembler "\n_?_Z1gILi1EEvPAplT_Li2E_Dd\[: \t\n\]" } }
Index: testsuite/g++.dg/dfp/mangle-4.C
===================================================================
--- testsuite/g++.dg/dfp/mangle-4.C	(revision 0)
+++ testsuite/g++.dg/dfp/mangle-4.C	(revision 0)
@@ -0,0 +1,35 @@ 
+// { dg-do compile }
+
+// Mangling of classes from std::decimal are special-cased.
+// Derived from g++.dg/abi/mangle30.C.
+
+namespace std {
+  namespace decimal {
+    class decimal64 {
+      public:
+	typedef float __decfloat64 __attribute__ ((mode (DD)));
+	explicit decimal64 (int __r):__val (__r) {}
+      private:
+	__decfloat64 __val;
+    };
+  }
+}
+
+struct A
+{
+  template <class T>
+  struct B
+  {
+    typedef T myT;
+  };
+};
+
+template <class T>
+void f (T t, typename T::template B<std::decimal::decimal64>::myT u, typename T::template B<int>::myT v);
+
+void foo ()
+{
+  f (A(), std::decimal::decimal64(0), 1);
+}
+
+// { dg-final { scan-assembler "_Z1fI1AEvT_NS1_1BIDdE3myTENS2_IiE3myTE" } }
Index: testsuite/g++.dg/dfp/mangle-5.C
===================================================================
--- testsuite/g++.dg/dfp/mangle-5.C	(revision 0)
+++ testsuite/g++.dg/dfp/mangle-5.C	(revision 0)
@@ -0,0 +1,29 @@ 
+// { dg-do compile }
+
+// Mangling of classes from std::decimal are special-cased.
+// Derived from g++.dg/abi/mangle35.C.
+
+namespace std {
+  namespace decimal {
+    class decimal128 {
+      public:
+	typedef float __decfloat128 __attribute__ ((mode (TD)));
+	explicit decimal128 (int __r):__val (__r) {}
+      private:
+	__decfloat128 __val;
+    };
+  }
+}
+
+template<void (*)()> struct A {};
+
+template<typename> void foo();
+
+template<typename T> A<foo<T> > bar();
+
+void baz()
+{
+  bar<std::decimal::decimal128>();
+}
+
+// { dg-final { scan-assembler "_Z3barIDeE1AIX3fooIT_EEEv" } }