diff mbox

[libstdc++/64239] Fix regex_iterator copying

Message ID CAG4ZjNn+Nrds6ab6qkPqS9ghXj2Pp77n8b1qkHFWi038rxQt=Q@mail.gmail.com
State New
Headers show

Commit Message

Tim Shen Dec. 11, 2014, 8:27 a.m. UTC
As discussed in Bugzilla.

Bootstrapped and tested.

Is it Ok to backport it to 4.9 branch, with _M_in_iterator kept unused?

Thanks! :)

Comments

Jonathan Wakely Dec. 12, 2014, 9:09 p.m. UTC | #1
On 11/12/14 00:27 -0800, Tim Shen wrote:
>As discussed in Bugzilla.
>
>Bootstrapped and tested.

OK for trunk.

>Is it Ok to backport it to 4.9 branch, with _M_in_iterator kept unused?

Yes, that's OK as well.

Thanks.
diff mbox

Patch

diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index cb6bc93..3afec37 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -1563,42 +1563,30 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
        */
       explicit
       match_results(const _Alloc& __a = _Alloc())
-      : _Base_type(__a), _M_in_iterator(false)
+      : _Base_type(__a)
       { }
 
       /**
        * @brief Copy constructs a %match_results.
        */
-      match_results(const match_results& __rhs)
-      : _Base_type(__rhs), _M_in_iterator(false)
-      { }
+      match_results(const match_results& __rhs) = default;
 
       /**
        * @brief Move constructs a %match_results.
        */
-      match_results(match_results&& __rhs) noexcept
-      : _Base_type(std::move(__rhs)), _M_in_iterator(false)
-      { }
+      match_results(match_results&& __rhs) noexcept = default;
 
       /**
        * @brief Assigns rhs to *this.
        */
       match_results&
-      operator=(const match_results& __rhs)
-      {
-	match_results(__rhs).swap(*this);
-	return *this;
-      }
+      operator=(const match_results& __rhs) = default;
 
       /**
        * @brief Move-assigns rhs to *this.
        */
       match_results&
-      operator=(match_results&& __rhs)
-      {
-	match_results(std::move(__rhs)).swap(*this);
-	return *this;
-      }
+      operator=(match_results&& __rhs) = default;
 
       /**
        * @brief Destroys a %match_results object.
@@ -1685,13 +1673,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       difference_type
       position(size_type __sub = 0) const
       {
-	// [28.12.1.4.5]
-	if (_M_in_iterator)
-	  return __sub < size() ? std::distance(_M_begin,
-						(*this)[__sub].first) : -1;
-	else
-	  return __sub < size() ? std::distance(this->prefix().first,
-						(*this)[__sub].first) : -1;
+	return __sub < size() ? std::distance(_M_begin,
+					      (*this)[__sub].first) : -1;
       }
 
       /**
@@ -1876,7 +1859,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
        */
       void
       swap(match_results& __that)
-      { _Base_type::swap(__that); }
+      {
+	_Base_type::swap(__that);
+	swap(_M_begin, __that._M_begin);
+      }
       //@}
 
     private:
@@ -1894,7 +1880,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				    regex_constants::match_flag_type);
 
       _Bi_iter _M_begin;
-      bool     _M_in_iterator;
     };
 
   typedef match_results<const char*>             cmatch;
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index 9692402..b676428 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -62,6 +62,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return false;
 
       typename match_results<_BiIter, _Alloc>::_Base_type& __res = __m;
+      __m._M_begin = __s;
       __res.resize(__re._M_automaton->_M_sub_count() + 2);
       for (auto& __it : __res)
 	__it.matched = false;
@@ -572,7 +573,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		      auto& __prefix = _M_match.at(_M_match.size());
 		      __prefix.first = __prefix_first;
 		      __prefix.matched = __prefix.first != __prefix.second;
-		      _M_match._M_in_iterator = true;
+		      // [28.12.1.4.5]
 		      _M_match._M_begin = _M_begin;
 		      return *this;
 		    }
@@ -587,7 +588,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      auto& __prefix = _M_match.at(_M_match.size());
 	      __prefix.first = __prefix_first;
 	      __prefix.matched = __prefix.first != __prefix.second;
-	      _M_match._M_in_iterator = true;
+	      // [28.12.1.4.5]
 	      _M_match._M_begin = _M_begin;
 	    }
 	  else
diff --git a/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/char/string_position_01.cc b/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/char/string_position_01.cc
index 5fa4ea7..91aa061 100644
--- a/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/char/string_position_01.cc
+++ b/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/char/string_position_01.cc
@@ -24,6 +24,7 @@ 
 // Tests iter->position() behavior
 
 #include <regex>
+#include <tuple>
 #include <testsuite_hooks.h>
 
 void
@@ -41,9 +42,53 @@  test01()
   }
 }
 
+// PR libstdc++/64239
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::regex re("\\w+");
+  std::string s("-a-b-c-");
+
+  std::tuple<int, int, const char*> expected[] =
+  {
+    std::make_tuple(1, 1, "a"),
+    std::make_tuple(3, 1, "b"),
+    std::make_tuple(5, 1, "c"),
+  };
+
+  int i = 0;
+  for (auto it1 = std::sregex_iterator(s.begin(), s.end(), re),
+       end = std::sregex_iterator(); it1 != end; ++it1, i++)
+    {
+      auto it2 = it1;
+      VERIFY(it1->position() == std::get<0>(expected[i]));
+      VERIFY(it1->length() == std::get<1>(expected[i]));
+      VERIFY(it1->str() == std::get<2>(expected[i]));
+      VERIFY(it2->position() == std::get<0>(expected[i]));
+      VERIFY(it2->length() == std::get<1>(expected[i]));
+      VERIFY(it2->str() == std::get<2>(expected[i]));
+    }
+}
+
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::smatch m;
+  std::string s = "abcde";
+  std::regex_search(s, m, std::regex("bcd"));
+  VERIFY(m.position() == 1);
+  VERIFY(m.position() == m.prefix().length());
+}
+
 int
 main()
 {
   test01();
+  test02();
+  test03();
   return 0;
 }