Patchwork [v3] fix libstdc++/51083

login
register
mail settings
Submitter Jonathan Wakely
Date Nov. 12, 2011, 3:59 p.m.
Message ID <CAH6eHdS=Cb7PEzyvkN4AuXO1NWfbqq=si=Zb2zdyYwNz1AqFZw@mail.gmail.com>
Download mbox | patch
Permalink /patch/125352/
State New
Headers show

Comments

Jonathan Wakely - Nov. 12, 2011, 3:59 p.m.
This allows __promote to be used like enable_if to constrain the TR1
and C++11 maths function overloads so they only work for floating
point and integral types.

        PR libstdc++/51083
        * include/ext/type_traits.h (__promote): Only define __type member
        for integral and floating point types, to prevent math functions
        participating in overload resolution for other types.
        (__promote_2, __promote_3, __promote_4): Use __promote in default
        template argument values, so deduction only succeeds for integral and
        floating point types.
        * testsuite/26_numerics/cmath/51083.cc: New.
        * testsuite/26_numerics/complex/51083.cc: New.
        * testsuite/tr1/8_c_compatibility/cmath/51083.cc: New.
        * testsuite/tr1/8_c_compatibility/complex/51083.cc: New.

tested x86_64-linux, committed to trunk.

I'm undecided whether this counts as a regression or not and if it
should be applied to the 4.6 branch - the testcases worked before TR1
was added or without -std=c++0x.
Paolo Carlini - Nov. 12, 2011, 4:24 p.m.
Hi

> I'm undecided whether this counts as a regression or not and if it
> should be applied to the 4.6 branch - the testcases worked before TR1
> was added or without -std=c++0x.

Thanks a lot for fixing this! About the branch, the patch seems safe enough to me, maybe just wait a couple if weeks?

Paolo
Jonathan Wakely - Nov. 12, 2011, 4:45 p.m.
On 12 November 2011 16:24, Paolo Carlini wrote:
> Hi
>
>> I'm undecided whether this counts as a regression or not and if it
>> should be applied to the 4.6 branch - the testcases worked before TR1
>> was added or without -std=c++0x.
>
> Thanks a lot for fixing this! About the branch, the patch seems safe enough to me, maybe just wait a couple if weeks?

Yeah, that's what I was thinking too - will do, thanks.
Gabriel Dos Reis - Nov. 12, 2011, 5:32 p.m.
On Sat, Nov 12, 2011 at 9:59 AM, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> This allows __promote to be used like enable_if to constrain the TR1
> and C++11 maths function overloads so they only work for floating
> point and integral types.
>
>        PR libstdc++/51083
>        * include/ext/type_traits.h (__promote): Only define __type member
>        for integral and floating point types, to prevent math functions
>        participating in overload resolution for other types.
>        (__promote_2, __promote_3, __promote_4): Use __promote in default
>        template argument values, so deduction only succeeds for integral and
>        floating point types.
>        * testsuite/26_numerics/cmath/51083.cc: New.
>        * testsuite/26_numerics/complex/51083.cc: New.
>        * testsuite/tr1/8_c_compatibility/cmath/51083.cc: New.
>        * testsuite/tr1/8_c_compatibility/complex/51083.cc: New.
>
> tested x86_64-linux, committed to trunk.
>
> I'm undecided whether this counts as a regression or not and if it
> should be applied to the 4.6 branch - the testcases worked before TR1
> was added or without -std=c++0x.
>

I'm OK with it everywhere.

Patch

Index: include/ext/type_traits.h
===================================================================
--- include/ext/type_traits.h	(revision 181320)
+++ include/ext/type_traits.h	(revision 181321)
@@ -161,44 +161,50 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __promote
     { typedef double __type; };
 
+  // No nested __type member for non-integer non-floating point types,
+  // allows this type to be used for SFINAE to constrain overloads in
+  // <cmath> and <complex> to only the intended types.
   template<typename _Tp>
     struct __promote<_Tp, false>
-    { typedef _Tp __type; };
+    { };
 
-  template<typename _Tp, typename _Up>
+  template<>
+    struct __promote<long double>
+    { typedef long double __type; };
+
+  template<>
+    struct __promote<double>
+    { typedef double __type; };
+
+  template<>
+    struct __promote<float>
+    { typedef float __type; };
+
+  template<typename _Tp, typename _Up,
+           typename _Tp2 = typename __promote<_Tp>::__type,
+           typename _Up2 = typename __promote<_Up>::__type>
     struct __promote_2
     {
-    private:
-      typedef typename __promote<_Tp>::__type __type1;
-      typedef typename __promote<_Up>::__type __type2;
-
-    public:
-      typedef __typeof__(__type1() + __type2()) __type;
+      typedef __typeof__(_Tp2() + _Up2()) __type;
     };
 
-  template<typename _Tp, typename _Up, typename _Vp>
+  template<typename _Tp, typename _Up, typename _Vp,
+           typename _Tp2 = typename __promote<_Tp>::__type,
+           typename _Up2 = typename __promote<_Up>::__type,
+           typename _Vp2 = typename __promote<_Vp>::__type>
     struct __promote_3
     {
-    private:
-      typedef typename __promote<_Tp>::__type __type1;
-      typedef typename __promote<_Up>::__type __type2;
-      typedef typename __promote<_Vp>::__type __type3;
-
-    public:
-      typedef __typeof__(__type1() + __type2() + __type3()) __type;
+      typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type;
     };
 
-  template<typename _Tp, typename _Up, typename _Vp, typename _Wp>
+  template<typename _Tp, typename _Up, typename _Vp, typename _Wp,
+           typename _Tp2 = typename __promote<_Tp>::__type,
+           typename _Up2 = typename __promote<_Up>::__type,
+           typename _Vp2 = typename __promote<_Vp>::__type,
+           typename _Wp2 = typename __promote<_Wp>::__type>
     struct __promote_4
     {
-    private:
-      typedef typename __promote<_Tp>::__type __type1;
-      typedef typename __promote<_Up>::__type __type2;
-      typedef typename __promote<_Vp>::__type __type3;
-      typedef typename __promote<_Wp>::__type __type4;
-
-    public:
-      typedef __typeof__(__type1() + __type2() + __type3() + __type4()) __type;
+      typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type;
     };
 
 _GLIBCXX_END_NAMESPACE_VERSION
Index: testsuite/26_numerics/complex/51083.cc
===================================================================
--- testsuite/26_numerics/complex/51083.cc	(revision 0)
+++ testsuite/26_numerics/complex/51083.cc	(revision 181321)
@@ -0,0 +1,54 @@ 
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+
+namespace a
+{
+  template<typename> class Mat { };
+
+  template<typename T> struct Mat2 : Mat<T> { };
+
+  template<typename T> int arg(Mat<T>) { return 1; }
+  template<typename T> int conj(Mat<T>) { return 1; }
+  template<typename T> int imag(Mat<T>) { return 1; }
+  template<typename T> int norm(Mat<T>) { return 1; }
+  template<typename T> int proj(Mat<T>) { return 1; }
+  template<typename T> int real(Mat<T>) { return 1; }
+
+  template<typename T, typename U> int pow(Mat<T>, U) { return 1; }
+  template<typename T, typename U> int pow(T, Mat<U>) { return 1; }
+}
+
+int main()
+{
+  int __attribute__((unused)) i;
+
+  using namespace std;
+
+  a::Mat2< std::complex<double> > c;
+  i = arg(c);
+  i = conj(c);
+  i = imag(c);
+  i = norm(c);
+  i = proj(c);
+  i = real(c);
+  i = pow(std::complex<float>(), c);
+  i = pow(c, std::complex<float>());
+}
Index: testsuite/26_numerics/cmath/51083.cc
===================================================================
--- testsuite/26_numerics/cmath/51083.cc	(revision 0)
+++ testsuite/26_numerics/cmath/51083.cc	(revision 181321)
@@ -0,0 +1,62 @@ 
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <cmath>
+
+namespace a
+{
+  template<typename> class Mat { };
+
+  template<typename T> struct Mat2 : Mat<T> { };
+
+  template<typename T>
+    int fdim(Mat<T>) { return 1; }
+
+  template<typename T, typename U>
+    int floor(Mat<T>, U) { return 1; }
+  template<typename T, typename U>
+    int floor(T, Mat<U>) { return 1; }
+
+  template<typename T, typename U, typename V>
+    int fma(Mat<T>, U, V) { return 1; }
+  template<typename T, typename U, typename V>
+    int fma(T, Mat<U>, V) { return 1; }
+  template<typename T, typename U, typename V>
+    int fma(T, U, Mat<V>) { return 1; }
+}
+
+int main()
+{
+  int __attribute__((unused)) i;
+
+  using namespace std;
+
+  a::Mat2<double> c;
+  i = fdim(c);
+  i = floor(c, 0.);
+  i = floor(0., c);
+  i = floor(c, 1);
+  i = floor(1, c);
+  i = fma(c, 0., 1.);
+  i = fma(0., c, 1.);
+  i = fma(0., 1., c);
+  i = fma(c, 0., 1);
+  i = fma(0., c, 1);
+  i = fma(0., 1, c);
+}
Index: testsuite/tr1/8_c_compatibility/complex/51083.cc
===================================================================
--- testsuite/tr1/8_c_compatibility/complex/51083.cc	(revision 0)
+++ testsuite/tr1/8_c_compatibility/complex/51083.cc	(revision 181321)
@@ -0,0 +1,54 @@ 
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr1/complex>
+
+namespace a
+{
+  template<typename> class Mat { };
+
+  template<typename T> struct Mat2 : Mat<T> { };
+
+  template<typename T> int arg(Mat<T>) { return 1; }
+  template<typename T> int conj(Mat<T>) { return 1; }
+  template<typename T> int imag(Mat<T>) { return 1; }
+  template<typename T> int norm(Mat<T>) { return 1; }
+  template<typename T> int proj(Mat<T>) { return 1; }
+  template<typename T> int real(Mat<T>) { return 1; }
+
+  template<typename T, typename U> int pow(Mat<T>, U) { return 1; }
+  template<typename T, typename U> int pow(T, Mat<U>) { return 1; }
+}
+
+int main()
+{
+  int __attribute__((unused)) i;
+
+  using namespace std::tr1;
+
+  a::Mat2< std::complex<double> > c;
+  i = arg(c);
+  i = conj(c);
+  i = imag(c);
+  i = norm(c);
+  i = proj(c);
+  i = real(c);
+  i = pow(std::complex<float>(), c);
+  i = pow(c, std::complex<float>());
+}
Index: testsuite/tr1/8_c_compatibility/cmath/51083.cc
===================================================================
--- testsuite/tr1/8_c_compatibility/cmath/51083.cc	(revision 0)
+++ testsuite/tr1/8_c_compatibility/cmath/51083.cc	(revision 181321)
@@ -0,0 +1,62 @@ 
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr1/cmath>
+
+namespace a
+{
+  template<typename> class Mat { };
+
+  template<typename T> struct Mat2 : Mat<T> { };
+
+  template<typename T>
+    int fdim(Mat<T>) { return 1; }
+
+  template<typename T, typename U>
+    int floor(Mat<T>, U) { return 1; }
+  template<typename T, typename U>
+    int floor(T, Mat<U>) { return 1; }
+
+  template<typename T, typename U, typename V>
+    int fma(Mat<T>, U, V) { return 1; }
+  template<typename T, typename U, typename V>
+    int fma(T, Mat<U>, V) { return 1; }
+  template<typename T, typename U, typename V>
+    int fma(T, U, Mat<V>) { return 1; }
+}
+
+int main()
+{
+  int __attribute__((unused)) i;
+
+  using namespace std::tr1;
+
+  a::Mat2<double> c;
+  i = fdim(c);
+  i = floor(c, 0.);
+  i = floor(0., c);
+  i = floor(c, 1);
+  i = floor(1, c);
+  i = fma(c, 0., 1.);
+  i = fma(0., c, 1.);
+  i = fma(0., 1., c);
+  i = fma(c, 0., 1);
+  i = fma(0., c, 1);
+  i = fma(0., 1, c);
+}