]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix std::match_results::end() for failed matches [PR102667]
authorJonathan Wakely <jwakely@redhat.com>
Mon, 11 Oct 2021 08:07:15 +0000 (09:07 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Mon, 11 Oct 2021 19:34:16 +0000 (20:34 +0100)
The end() function needs to consider whether the underlying vector is
empty, not whether the match_results object is empty. That's because the
underlying vector will always contain at least three elements for a
match_results object that is "ready". It contains three extra elements
which are stored in the vector but are not considered part of sequence,
and so should not be part of the [begin(),end()) range.

libstdc++-v3/ChangeLog:

PR libstdc++/102667
* include/bits/regex.h (match_result::empty()): Optimize by
calling the base function directly.
(match_results::end()): Check _Base_type::empty() not empty().
* testsuite/28_regex/match_results/102667.C: New test.

libstdc++-v3/include/bits/regex.h
libstdc++-v3/testsuite/28_regex/match_results/102667.C [new file with mode: 0644]

index ff908da3e9422f5d5e67a9a52f2b45493202e55b..bf02bff7c4921bd66a94a8174f37e45bddbf2d76 100644 (file)
@@ -1828,7 +1828,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        */
       _GLIBCXX_NODISCARD bool
       empty() const noexcept
-      { return size() == 0; }
+      { return _Unchecked::size() <= 3; }
 
       ///@}
 
@@ -1946,7 +1946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        */
       const_iterator
       end() const noexcept
-      { return _Base_type::end() - (empty() ? 0 : 3); }
+      { return _Base_type::end() - (_Base_type::empty() ? 0 : 3); }
 
       /**
        * @brief Gets an iterator to one-past-the-end of the collection.
diff --git a/libstdc++-v3/testsuite/28_regex/match_results/102667.C b/libstdc++-v3/testsuite/28_regex/match_results/102667.C
new file mode 100644 (file)
index 0000000..9e38c9e
--- /dev/null
@@ -0,0 +1,39 @@
+// { dg-do run { target c++11 } }
+
+#include <regex>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::cmatch sm;
+  VERIFY( sm.empty() );
+  VERIFY( sm.size() == 0 );
+  VERIFY( sm.begin() == sm.end() );  // PR libstdc++/83600
+
+  bool matched = std::regex_match("a", sm, std::regex("b"));
+  VERIFY( ! matched );
+  VERIFY( sm.ready() );
+  VERIFY( sm.empty() );
+  VERIFY( sm.size() == 0 );
+  VERIFY( sm.begin() == sm.end() ); // PR libstdc++/102667
+
+  matched = std::regex_match("a", sm, std::regex("a"));
+  VERIFY( matched );
+  VERIFY( sm.ready() );
+  VERIFY( ! sm.empty() );
+  VERIFY( sm.size() == 1 );
+  VERIFY( (sm.end() - sm.begin()) == 1 );
+
+  matched = std::regex_search("abcd", sm, std::regex("(b)(c)"));
+  VERIFY( matched );
+  VERIFY( sm.ready() );
+  VERIFY( ! sm.empty() );
+  VERIFY( sm.size() == 3 );
+  VERIFY( (sm.end() - sm.begin()) == 3 );
+}
+
+int main()
+{
+  test01();
+}