diff mbox

libstdc++/69116 Constrain std::valarray functions and operators

Message ID 20160122211553.GH15084@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Jan. 22, 2016, 9:15 p.m. UTC
The example in the PR is a sneaky little problem. When <valarray> is
included the following overload is declared:

template<typename _Tp>
_Expr</* here be expression templates */>
operator<<(const _Tp& __t, const valarray<_Tp>& __v);

This is a candidate function for any "a << b" expression with
namespace std as an associated namespace. In order to do overload
resolution valarray<decltype(a)> gets instantiated to see if there is
a conversion from decltype(b). When decltype(a) is an abstract type
valarray<decltype(a)> results in an error outside the immediate
context, and overload resolution stops with an error.

This could happen for any of the overloaded operators and functions
that work with valarray, so my solution is to adjust the __fun<> class
template so that the result type of valarray operations is not defined
for types that cannot be used in valarray.  When the result_type is
missing the valarray operators give a SFINAE deduction failure not a
hard error.

Currently the check is !__is_abstract(_Tp) but it could be tweaked to
also check other conditions that cause a problem.

The new test uses -std=gnu++98 because if it uses a later standard
then it fails due to similar unconstrained operators in <complex>, and
std::complex<T> also fails if is_abstract<T>, so I'll have to fix that
next.

Tested powerpc64-linux, comimtted to trunk.

This is a regression, caused by the front end starting to diagnose the
invalid library instantiations more eagerly. The fix seems simple and
safe, so I plan to backport it to the branches too.

Comments

Jonathan Wakely Feb. 10, 2016, 11:25 a.m. UTC | #1
On 22/01/16 21:15 +0000, Jonathan Wakely wrote:
>This is a regression, caused by the front end starting to diagnose the
>invalid library instantiations more eagerly. The fix seems simple and
>safe, so I plan to backport it to the branches too.

Committed to the branches too.
diff mbox

Patch

commit 64f205467ab5822f4b75f9ae14933c52d5062f66
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jan 22 17:09:06 2016 +0000

    Constrain std::valarray functions and operators
    
    	PR libstdc++/69116
    	* include/bits/valarray_before.h (__fun, __fun_with_valarray): Only
    	define result_type for types which can be safely used with valarrays.
    	* testsuite/26_numerics/valarray/69116.cc: New.

diff --git a/libstdc++-v3/include/bits/valarray_before.h b/libstdc++-v3/include/bits/valarray_before.h
index 3325bf8..86136f4 100644
--- a/libstdc++-v3/include/bits/valarray_before.h
+++ b/libstdc++-v3/include/bits/valarray_before.h
@@ -331,14 +331,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return pow(__x, __y); }
   };
 
+  template<typename _Tp, bool _IsValidValarrayValue = !__is_abstract(_Tp)>
+    struct __fun_with_valarray
+    {
+      typedef _Tp result_type;
+    };
+
+  template<typename _Tp>
+    struct __fun_with_valarray<_Tp, false>
+    {
+      // No result type defined for invalid value types.
+    };
 
   // We need these bits in order to recover the return type of
   // some functions/operators now that we're no longer using
   // function templates.
   template<typename, typename _Tp>
-    struct __fun
+    struct __fun : __fun_with_valarray<_Tp>
     {
-      typedef _Tp result_type;
     };
 
   // several specializations for relational operators.
diff --git a/libstdc++-v3/testsuite/26_numerics/valarray/69116.cc b/libstdc++-v3/testsuite/26_numerics/valarray/69116.cc
new file mode 100644
index 0000000..ef98267
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/valarray/69116.cc
@@ -0,0 +1,53 @@ 
+// Copyright (C) 2016 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/>.
+
+// { dg-do compile }
+// { dg-options "-std=gnu++98" }
+
+// libstdc++/69116
+
+#include <exception>
+#include <valarray>
+
+template<typename T>
+  void foo(const T&) { }
+
+struct X : std::exception // makes namespace std an associated namespace
+{
+  virtual void pure() = 0;
+
+  typedef void(*func_type)(const X&);
+
+  void operator+(func_type) const;
+  void operator-(func_type) const;
+  void operator*(func_type) const;
+  void operator/(func_type) const;
+  void operator%(func_type) const;
+  void operator<<(func_type) const;
+  void operator>>(func_type) const;
+};
+
+void foo(X& x)
+{
+  x + foo;
+  x - foo;
+  x * foo;
+  x / foo;
+  x % foo;
+  x << foo;
+  x >> foo;
+}