Commit 2bde8cac by Tim Shen Committed by Tim Shen

re PR libstdc++/63199 (Inserting std::wregex to std::vector loses some std::wregex values)

	PR libstdc++/63199
	* include/bits/regex.h (basic_regex::basic_regex, basic_regex::assign,
	basic_regex::imbue, basic_regex::getloc, basic_regex::swap): Add
	_M_loc for basic_regex.
	* include/bits/regex_automaton.h: Add _M_traits for _NFA.
	* include/bits/regex_compiler.h (_Compiler::_M_get_nfa, __compile_nfa):
	Make _Compiler::_M_nfa heap allocated.
	* include/bits/regex_compiler.tcc (_Compiler::_Compiler): Make
	_Compiler::_M_nfa heap allocated.
	* include/bits/regex_executor.h (_Executor::_M_is_word):
	Fix accessing _M_traits.
	* include/bits/regex_executor.tcc (_Executor::_M_dfs):
	Fix accessing _M_traits.
	* testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/63199.cc:
	New testcase.

From-SVN: r215578
parent 21a9ce6e
2014-09-25 Tim Shen <timshen@google.com>
PR libstdc++/63199
* include/bits/regex.h (basic_regex::basic_regex, basic_regex::assign,
basic_regex::imbue, basic_regex::getloc, basic_regex::swap): Add
_M_loc for basic_regex.
* include/bits/regex_automaton.h: Add _M_traits for _NFA.
* include/bits/regex_compiler.h (_Compiler::_M_get_nfa, __compile_nfa):
Make _Compiler::_M_nfa heap allocated.
* include/bits/regex_compiler.tcc (_Compiler::_Compiler): Make
_Compiler::_M_nfa heap allocated.
* include/bits/regex_executor.h (_Executor::_M_is_word):
Fix accessing _M_traits.
* include/bits/regex_executor.tcc (_Executor::_M_dfs):
Fix accessing _M_traits.
* testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/63199.cc:
New testcase.
2014-09-24 Jonathan Wakely <jwakely@redhat.com> 2014-09-24 Jonathan Wakely <jwakely@redhat.com>
* config/abi/pre/gnu.ver: Make GLIBCXX_3.4 patterns stricter so the * config/abi/pre/gnu.ver: Make GLIBCXX_3.4 patterns stricter so the
......
...@@ -64,7 +64,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -64,7 +64,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline std::shared_ptr<_NFA<_TraitsT>> inline std::shared_ptr<_NFA<_TraitsT>>
__compile_nfa(const typename _TraitsT::char_type* __first, __compile_nfa(const typename _TraitsT::char_type* __first,
const typename _TraitsT::char_type* __last, const typename _TraitsT::char_type* __last,
const _TraitsT& __traits, const typename _TraitsT::locale_type& __loc,
regex_constants::syntax_option_type __flags); regex_constants::syntax_option_type __flags);
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
...@@ -433,7 +433,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -433,7 +433,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* character sequence. * character sequence.
*/ */
basic_regex() basic_regex()
: _M_flags(ECMAScript), _M_automaton(nullptr) : _M_flags(ECMAScript), _M_loc(), _M_original_str(), _M_automaton(nullptr)
{ } { }
/** /**
...@@ -481,10 +481,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -481,10 +481,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* *
* @param __rhs A @p regex object. * @param __rhs A @p regex object.
*/ */
basic_regex(const basic_regex&& __rhs) noexcept basic_regex(basic_regex&& __rhs) noexcept = default;
: _M_flags(__rhs._M_flags), _M_traits(__rhs._M_traits),
_M_automaton(std::move(__rhs._M_automaton))
{ }
/** /**
* @brief Constructs a basic regular expression from the string * @brief Constructs a basic regular expression from the string
...@@ -520,12 +517,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -520,12 +517,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_regex(_FwdIter __first, _FwdIter __last, basic_regex(_FwdIter __first, _FwdIter __last,
flag_type __f = ECMAScript) flag_type __f = ECMAScript)
: _M_flags(__f), : _M_flags(__f),
_M_loc(),
_M_original_str(__first, __last), _M_original_str(__first, __last),
_M_automaton(__detail::__compile_nfa(_M_original_str.c_str(), _M_automaton(__detail::__compile_nfa<_Rx_traits>(
_M_original_str.c_str() _M_original_str.c_str(),
+ _M_original_str.size(), _M_original_str.c_str() + _M_original_str.size(),
_M_traits, _M_loc,
_M_flags)) _M_flags))
{ } { }
/** /**
...@@ -662,9 +660,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -662,9 +660,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_flags = __flags; _M_flags = __flags;
_M_original_str.assign(__s.begin(), __s.end()); _M_original_str.assign(__s.begin(), __s.end());
auto __p = _M_original_str.c_str(); auto __p = _M_original_str.c_str();
_M_automaton = __detail::__compile_nfa(__p, _M_automaton = __detail::__compile_nfa<_Rx_traits>(
__p + _M_original_str.size(), __p,
_M_traits, _M_flags); __p + _M_original_str.size(),
_M_loc,
_M_flags);
return *this; return *this;
} }
...@@ -728,9 +728,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -728,9 +728,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
locale_type locale_type
imbue(locale_type __loc) imbue(locale_type __loc)
{ {
auto __ret = _M_traits.imbue(__loc); std::swap(__loc, _M_loc);
this->assign(_M_original_str, _M_flags); if (_M_automaton != nullptr)
return __ret; this->assign(_M_original_str, _M_flags);
return __loc;
} }
/** /**
...@@ -739,7 +740,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -739,7 +740,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/ */
locale_type locale_type
getloc() const getloc() const
{ return _M_traits.getloc(); } { return _M_loc; }
// [7.8.6] swap // [7.8.6] swap
/** /**
...@@ -751,7 +752,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -751,7 +752,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(basic_regex& __rhs) swap(basic_regex& __rhs)
{ {
std::swap(_M_flags, __rhs._M_flags); std::swap(_M_flags, __rhs._M_flags);
std::swap(_M_traits, __rhs._M_traits); std::swap(_M_loc, __rhs._M_loc);
std::swap(_M_original_str, __rhs._M_original_str);
std::swap(_M_automaton, __rhs._M_automaton); std::swap(_M_automaton, __rhs._M_automaton);
} }
...@@ -761,7 +763,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -761,7 +763,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ _M_automaton->_M_dot(__ostr); } { _M_automaton->_M_dot(__ostr); }
#endif #endif
protected: private:
typedef std::shared_ptr<__detail::_NFA<_Rx_traits>> _AutomatonPtr; typedef std::shared_ptr<__detail::_NFA<_Rx_traits>> _AutomatonPtr;
template<typename _Bp, typename _Ap, typename _Cp, typename _Rp, template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
...@@ -775,7 +777,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -775,7 +777,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend class __detail::_Executor; friend class __detail::_Executor;
flag_type _M_flags; flag_type _M_flags;
_Rx_traits _M_traits; locale_type _M_loc;
basic_string<_Ch_type> _M_original_str; basic_string<_Ch_type> _M_original_str;
_AutomatonPtr _M_automaton; _AutomatonPtr _M_automaton;
}; };
......
...@@ -160,7 +160,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -160,7 +160,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _State<_TraitsT> _StateT; typedef _State<_TraitsT> _StateT;
typedef _Matcher<typename _TraitsT::char_type> _MatcherT; typedef _Matcher<typename _TraitsT::char_type> _MatcherT;
using _NFA_base::_NFA_base; _NFA(const typename _TraitsT::locale_type& __loc, _FlagT __flags)
: _NFA_base(__flags)
{ _M_traits.imbue(__loc); }
// for performance reasons _NFA objects should only be moved not copied // for performance reasons _NFA objects should only be moved not copied
_NFA(const _NFA&) = delete; _NFA(const _NFA&) = delete;
...@@ -272,6 +274,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -272,6 +274,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::ostream& std::ostream&
_M_dot(std::ostream& __ostr) const; _M_dot(std::ostream& __ostr) const;
#endif #endif
public:
_TraitsT _M_traits;
}; };
/// Describes a sequence of one or more %_State, its current start /// Describes a sequence of one or more %_State, its current start
......
...@@ -57,11 +57,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -57,11 +57,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef regex_constants::syntax_option_type _FlagT; typedef regex_constants::syntax_option_type _FlagT;
_Compiler(_IterT __b, _IterT __e, _Compiler(_IterT __b, _IterT __e,
const _TraitsT& __traits, _FlagT __flags); const typename _TraitsT::locale_type& __traits, _FlagT __flags);
std::shared_ptr<_RegexT> std::shared_ptr<_RegexT>
_M_get_nfa() _M_get_nfa()
{ return make_shared<_RegexT>(std::move(_M_nfa)); } { return std::move(_M_nfa); }
private: private:
typedef _Scanner<_CharT> _ScannerT; typedef _Scanner<_CharT> _ScannerT;
...@@ -135,24 +135,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -135,24 +135,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return ret; return ret;
} }
_FlagT _M_flags; _FlagT _M_flags;
const _TraitsT& _M_traits; _ScannerT _M_scanner;
const _CtypeT& _M_ctype; shared_ptr<_RegexT> _M_nfa;
_ScannerT _M_scanner; _StringT _M_value;
_RegexT _M_nfa; _StackT _M_stack;
_StringT _M_value; const _TraitsT& _M_traits;
_StackT _M_stack; const _CtypeT& _M_ctype;
}; };
template<typename _TraitsT> template<typename _TraitsT>
inline std::shared_ptr<_NFA<_TraitsT>> inline std::shared_ptr<_NFA<_TraitsT>>
__compile_nfa(const typename _TraitsT::char_type* __first, __compile_nfa(const typename _TraitsT::char_type* __first,
const typename _TraitsT::char_type* __last, const typename _TraitsT::char_type* __last,
const _TraitsT& __traits, const typename _TraitsT::locale_type& __loc,
regex_constants::syntax_option_type __flags) regex_constants::syntax_option_type __flags)
{ {
using _Cmplr = _Compiler<_TraitsT>; using _Cmplr = _Compiler<_TraitsT>;
return _Cmplr(__first, __last, __traits, __flags)._M_get_nfa(); return _Cmplr(__first, __last, __loc, __flags)._M_get_nfa();
} }
// [28.13.14] // [28.13.14]
......
...@@ -125,8 +125,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -125,8 +125,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_is_word(_CharT __ch) const _M_is_word(_CharT __ch) const
{ {
static const _CharT __s[2] = { 'w' }; static const _CharT __s[2] = { 'w' };
return _M_re._M_traits.isctype return _M_re._M_automaton->_M_traits.isctype
(__ch, _M_re._M_traits.lookup_classname(__s, __s+1)); (__ch, _M_re._M_automaton->_M_traits.lookup_classname(__s, __s+1));
} }
bool bool
......
...@@ -312,9 +312,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -312,9 +312,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__last != _M_end && __tmp != __submatch.second; __last != _M_end && __tmp != __submatch.second;
++__tmp) ++__tmp)
++__last; ++__last;
if (_M_re._M_traits.transform(__submatch.first, if (_M_re._M_automaton->_M_traits.transform(__submatch.first,
__submatch.second) __submatch.second)
== _M_re._M_traits.transform(_M_current, __last)) == _M_re._M_automaton->_M_traits.transform(_M_current, __last))
{ {
if (__last != _M_current) if (__last != _M_current)
{ {
...@@ -380,8 +380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -380,8 +380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
case _S_opcode_alternative: case _S_opcode_alternative:
if (_M_nfa._M_flags & regex_constants::ECMAScript) if (_M_nfa._M_flags & regex_constants::ECMAScript)
{ {
// TODO: Let DFS support ECMAScript's alternative operation. // TODO: Let BFS support ECMAScript's alternative operation.
_GLIBCXX_DEBUG_ASSERT(!__dfs_mode); _GLIBCXX_DEBUG_ASSERT(__dfs_mode);
_M_dfs(__match_mode, __state._M_alt); _M_dfs(__match_mode, __state._M_alt);
// Pick lhs if it matches. Only try rhs if it doesn't. // Pick lhs if it matches. Only try rhs if it doesn't.
if (!_M_has_sol) if (!_M_has_sol)
......
// { dg-options "-std=gnu++11" }
//
// Copyright (C) 2014 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 <regex>
#include <testsuite_hooks.h>
#include <testsuite_regex.h>
using namespace __gnu_test;
using namespace std;
// libstdc++/63199
void
test01()
{
bool test __attribute__((unused)) = true;
std::setlocale(LC_ALL, "");
std::wstring current_token(L"II.");
std::vector<std::wregex> regex_vector;
for (int i = 0; i < 4; ++i)
{
std::regex_constants::syntax_option_type flag;
flag = std::regex_constants::ECMAScript | std::regex_constants::icase;
std::wregex reg;
reg.imbue(std::locale(""));
reg.assign(L"^(M*(?:CM|DC{1,3}|D|CD|C{1,3}){0,1}(?:XC|LX{1,3}|L|XL|X{1,3}){0,1}(?:IX|VI{0,3}|IV|I{1,3}){0,1}\\.)$", flag);
regex_vector.emplace_back(reg);
}
for (auto cit = regex_vector.cbegin(); cit != regex_vector.cend(); ++cit)
{
std::wstring::const_iterator it1 = current_token.begin();
std::wstring::const_iterator it2 = current_token.end();
std::wsmatch current_token_match;
regex_match_debug(it1, it2, current_token_match, *cit);
VERIFY(current_token_match[0] == current_token);
VERIFY(current_token_match[1] == current_token);
}
}
int
main()
{
test01();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment