PR libstdc++/71500 restore C++11 compatibility in <regex>
authorJonathan Wakely <redi@gcc.gnu.org>
Tue, 19 Sep 2017 17:06:12 +0000 (18:06 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 19 Sep 2017 17:06:12 +0000 (18:06 +0100)
PR libstdc++/71500
* include/bits/regex_executor.tcc
(_Backref_matcher<BidIt, regex_traits<C>>::_M_apply): Use
std::__equal4 instead of C++14 4-iterator overloads of std::equal.
* include/bits/stl_algobase.h (__equal4): New functions implementing
4-iterator overloads of std::equal for use in C++11.
(equal(It1, It1, It2, It2), equal(It1, It1, It2, It2, BinaryPred)):
Move function bodies to new __equal4 functions.
* testsuite/28_regex/simple_c++11.cc: New.

From-SVN: r252981

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/regex_executor.tcc
libstdc++-v3/include/bits/stl_algobase.h
libstdc++-v3/testsuite/28_regex/simple_c++11.cc [new file with mode: 0644]

index 3c75c7639cad1b0fa2b8c76ac6222a6e96186eea..f9424a58c8a506474e7a9e5bfd80be91b17f377d 100644 (file)
@@ -1,5 +1,15 @@
 2017-09-19  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/71500
+       * include/bits/regex_executor.tcc
+       (_Backref_matcher<BidIt, regex_traits<C>>::_M_apply): Use
+       std::__equal4 instead of C++14 4-iterator overloads of std::equal.
+       * include/bits/stl_algobase.h (__equal4): New functions implementing
+       4-iterator overloads of std::equal for use in C++11.
+       (equal(It1, It1, It2, It2), equal(It1, It1, It2, It2, BinaryPred)):
+       Move function bodies to new __equal4 functions.
+       * testsuite/28_regex/simple_c++11.cc: New.
+
        PR libstdc++/82254
        * include/std/type_traits (__is_invocable): Add partial specialization
        for INVOKE<void> case and remove is_void<R> check from partial
 2017-09-11  Tim Shen  <timshen@google.com>
 
        PR libstdc++/71500
-       * include/bits/regex_executor.tcc: Support icase in regex_tratis<...>
+       * include/bits/regex_executor.tcc: Support icase in regex_traits<...>
        for back reference matches.
        * testsuite/28_regex/regression.cc: Test case.
 
index f6149fecf9d81585b04a720271cb8ef2b34870a9..2ceba35e7b828e6f60afaf49cbf54678b6c2a3e2 100644 (file)
@@ -366,17 +366,17 @@ namespace __detail
               _BiIter __actual_end)
       {
        if (!_M_icase)
-         return std::equal(__expected_begin, __expected_end,
-                           __actual_begin, __actual_end);
+         return std::__equal4(__expected_begin, __expected_end,
+                              __actual_begin, __actual_end);
        typedef std::ctype<_CharT> __ctype_type;
        const auto& __fctyp = use_facet<__ctype_type>(_M_traits.getloc());
-       return std::equal(__expected_begin, __expected_end,
-                         __actual_begin, __actual_end,
-                         [this, &__fctyp](_CharT __lhs, _CharT __rhs)
-                         {
-                           return __fctyp.tolower(__lhs)
-                               == __fctyp.tolower(__rhs);
-                         });
+       return std::__equal4(__expected_begin, __expected_end,
+                            __actual_begin, __actual_end,
+                            [this, &__fctyp](_CharT __lhs, _CharT __rhs)
+                            {
+                              return __fctyp.tolower(__lhs)
+                                == __fctyp.tolower(__rhs);
+                            });
       }
 
       bool _M_icase;
index f68ecb22b8211532a279e920ce6a6db4b43a74f6..a80934c4faaabf94b27bfc4f1365682e1812462a 100644 (file)
@@ -1082,6 +1082,60 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       return true;
     }
 
+#if __cplusplus >= 201103L
+  // 4-iterator version of std::equal<It1, It2> for use in C++11.
+  template<typename _II1, typename _II2>
+    inline bool
+    __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2)
+    {
+      using _RATag = random_access_iterator_tag;
+      using _Cat1 = typename iterator_traits<_II1>::iterator_category;
+      using _Cat2 = typename iterator_traits<_II2>::iterator_category;
+      using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>;
+      if (_RAIters())
+       {
+         auto __d1 = std::distance(__first1, __last1);
+         auto __d2 = std::distance(__first2, __last2);
+         if (__d1 != __d2)
+           return false;
+         return _GLIBCXX_STD_A::equal(__first1, __last1, __first2);
+       }
+
+      for (; __first1 != __last1 && __first2 != __last2;
+         ++__first1, (void)++__first2)
+       if (!(*__first1 == *__first2))
+         return false;
+      return __first1 == __last1 && __first2 == __last2;
+    }
+
+  // 4-iterator version of std::equal<It1, It2, BinaryPred> for use in C++11.
+  template<typename _II1, typename _II2, typename _BinaryPredicate>
+    inline bool
+    __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2,
+            _BinaryPredicate __binary_pred)
+    {
+      using _RATag = random_access_iterator_tag;
+      using _Cat1 = typename iterator_traits<_II1>::iterator_category;
+      using _Cat2 = typename iterator_traits<_II2>::iterator_category;
+      using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>;
+      if (_RAIters())
+       {
+         auto __d1 = std::distance(__first1, __last1);
+         auto __d2 = std::distance(__first2, __last2);
+         if (__d1 != __d2)
+           return false;
+         return _GLIBCXX_STD_A::equal(__first1, __last1, __first2,
+                                      __binary_pred);
+       }
+
+      for (; __first1 != __last1 && __first2 != __last2;
+         ++__first1, (void)++__first2)
+       if (!bool(__binary_pred(*__first1, *__first2)))
+         return false;
+      return __first1 == __last1 && __first2 == __last2;
+    }
+#endif // C++11
+
 #if __cplusplus > 201103L
 
 #define __cpp_lib_robust_nonmodifying_seq_ops 201304
@@ -1112,24 +1166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-      using _RATag = random_access_iterator_tag;
-      using _Cat1 = typename iterator_traits<_II1>::iterator_category;
-      using _Cat2 = typename iterator_traits<_II2>::iterator_category;
-      using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>;
-      if (_RAIters())
-       {
-         auto __d1 = std::distance(__first1, __last1);
-         auto __d2 = std::distance(__first2, __last2);
-         if (__d1 != __d2)
-           return false;
-         return _GLIBCXX_STD_A::equal(__first1, __last1, __first2);
-       }
-
-      for (; __first1 != __last1 && __first2 != __last2;
-         ++__first1, (void)++__first2)
-       if (!(*__first1 == *__first2))
-         return false;
-      return __first1 == __last1 && __first2 == __last2;
+      return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2);
     }
 
   /**
@@ -1159,27 +1196,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-      using _RATag = random_access_iterator_tag;
-      using _Cat1 = typename iterator_traits<_IIter1>::iterator_category;
-      using _Cat2 = typename iterator_traits<_IIter2>::iterator_category;
-      using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>;
-      if (_RAIters())
-       {
-         auto __d1 = std::distance(__first1, __last1);
-         auto __d2 = std::distance(__first2, __last2);
-         if (__d1 != __d2)
-           return false;
-         return _GLIBCXX_STD_A::equal(__first1, __last1, __first2,
-                                      __binary_pred);
-       }
-
-      for (; __first1 != __last1 && __first2 != __last2;
-         ++__first1, (void)++__first2)
-       if (!bool(__binary_pred(*__first1, *__first2)))
-         return false;
-      return __first1 == __last1 && __first2 == __last2;
+      return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2,
+                                     __binary_pred);
     }
-#endif
+#endif // C++14
 
   /**
    *  @brief Performs @b dictionary comparison on ranges.
diff --git a/libstdc++-v3/testsuite/28_regex/simple_c++11.cc b/libstdc++-v3/testsuite/28_regex/simple_c++11.cc
new file mode 100644 (file)
index 0000000..2cfa503
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (C) 2017 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-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <regex>
+
+// Ensure compilation of trivial example still works with C++11.
+// https://gcc.gnu.org/ml/libstdc++/2017-09/msg00040.html
+std::regex r{""};
+std::cmatch m;
+bool b = regex_match("", m, r);