Skip to content

Commit 7d38b70

Browse files
1 parent dbe76cc commit 7d38b70

File tree

4 files changed

+405
-30
lines changed

4 files changed

+405
-30
lines changed

stl/inc/regex

+55-30
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,7 @@ public:
17211721

17221722
private:
17231723
// lexing
1724-
void _Error(regex_constants::error_type);
1724+
[[noreturn]] void _Error(regex_constants::error_type);
17251725

17261726
bool _Is_esc() const;
17271727
void _Trans();
@@ -2912,7 +2912,8 @@ void _Builder<_FwdIt, _Elem, _RxTraits>::_Add_range2(const _Elem _Arg0, const _E
29122912

29132913
_Node->_Small->_Mark(_Ex0);
29142914
}
2915-
if (_Ex1 >= _Ex0) {
2915+
2916+
if ((_Flags & regex_constants::collate) || _Ex1 >= _Ex0) {
29162917
if (_Ex1 - _Ex0 < _Get_tmax()) {
29172918
for (; _Ex0 <= _Ex1; ++_Ex0) {
29182919
_Add_char_to_array(static_cast<_Elem>(_Ex0));
@@ -3364,6 +3365,20 @@ bool _Lookup_range(unsigned int _Ch, const _Buf<_Elem>* _Bufptr) { // check whet
33643365
return false;
33653366
}
33663367

3368+
template <class _Elem, class _RxTraits>
3369+
bool _Lookup_collating_range(const _Elem _Ch, const _Buf<_Elem>* const _Bufptr, const _RxTraits& _Traits) {
3370+
const typename _RxTraits::string_type _Str = _Traits.transform(_STD addressof(_Ch), _STD addressof(_Ch) + 1);
3371+
for (unsigned int _Ix = 0; _Ix < _Bufptr->_Size(); _Ix += 2) { // check current position
3372+
const _Elem _Left = _Bufptr->_At(_Ix);
3373+
const _Elem _Right = _Bufptr->_At(_Ix + 1);
3374+
if (_Traits.transform(_STD addressof(_Left), _STD addressof(_Left) + 1) <= _Str
3375+
&& _Str <= _Traits.transform(_STD addressof(_Right), _STD addressof(_Right) + 1)) {
3376+
return true;
3377+
}
3378+
}
3379+
return false;
3380+
}
3381+
33673382
template <class _Elem, class _RxTraits>
33683383
bool _Lookup_equiv(typename _RxTraits::_Uelem _Ch, const _Sequence<_Elem>* _Eq, const _RxTraits& _Traits) {
33693384
// check whether _Ch is in _Eq
@@ -3407,35 +3422,36 @@ _BidIt _Lookup_coll(_BidIt _First, _BidIt _Last, const _Sequence<_Elem>* _Eq) {
34073422
template <class _BidIt, class _Elem, class _RxTraits, class _It>
34083423
bool _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Do_class(_Node_base* _Nx) { // apply bracket expression
34093424
bool _Found;
3410-
auto _Ch = static_cast<typename _RxTraits::_Uelem>(*_Tgt_state._Cur);
3425+
_Elem _Ch = *_Tgt_state._Cur;
34113426
if (_Sflags & regex_constants::icase) {
3412-
_Ch = static_cast<typename _RxTraits::_Uelem>(_Traits.translate_nocase(static_cast<_Elem>(_Ch)));
3427+
_Ch = _Traits.translate_nocase(_Ch);
3428+
} else if (_Sflags & regex_constants::collate) {
3429+
_Ch = _Traits.translate(_Ch);
34133430
}
3431+
const auto _UCh = static_cast<typename _RxTraits::_Uelem>(_Ch);
34143432

34153433
_It _Res0 = _Tgt_state._Cur;
34163434
++_Res0;
34173435
_It _Resx;
34183436
_Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Nx);
34193437
if (_Node->_Coll
3420-
&& (_Resx = _Lookup_coll(_Tgt_state._Cur, _End, _Node->_Coll))
3438+
&& (_Resx = _STD _Lookup_coll(_Tgt_state._Cur, _End, _Node->_Coll))
34213439
!= _Tgt_state._Cur) { // check for collation element
34223440
_Res0 = _Resx;
34233441
_Found = true;
34243442
} else if (_Node->_Ranges
3425-
&& (_Lookup_range(static_cast<typename _RxTraits::_Uelem>(
3426-
_Sflags & regex_constants::collate ? _Traits.translate(static_cast<_Elem>(_Ch))
3427-
: static_cast<_Elem>(_Ch)),
3428-
_Node->_Ranges))) {
3443+
&& (_Sflags & regex_constants::collate ? _STD _Lookup_collating_range(_Ch, _Node->_Ranges, _Traits)
3444+
: _STD _Lookup_range(_UCh, _Node->_Ranges))) {
34293445
_Found = true;
3430-
} else if (_Ch < _Bmp_max) {
3431-
_Found = _Node->_Small && _Node->_Small->_Find(_Ch);
3446+
} else if (_UCh < _Bmp_max) {
3447+
_Found = _Node->_Small && _Node->_Small->_Find(_UCh);
34323448
} else if (_Node->_Large
34333449
&& _STD find(_Node->_Large->_Str(), _Node->_Large->_Str() + _Node->_Large->_Size(), _Ch)
34343450
!= _Node->_Large->_Str() + _Node->_Large->_Size()) {
34353451
_Found = true;
3436-
} else if (_Node->_Classes != 0 && _Traits.isctype(static_cast<_Elem>(_Ch), _Node->_Classes)) {
3452+
} else if (_Node->_Classes != typename _RxTraits::char_class_type{} && _Traits.isctype(_Ch, _Node->_Classes)) {
34373453
_Found = true;
3438-
} else if (_Node->_Equiv && _Lookup_equiv(_Ch, _Node->_Equiv, _Traits)) {
3454+
} else if (_Node->_Equiv && _STD _Lookup_equiv(_UCh, _Node->_Equiv, _Traits)) {
34393455
_Found = true;
34403456
} else {
34413457
_Found = false;
@@ -3762,34 +3778,36 @@ _BidIt _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Skip(_BidIt _First_arg, _BidIt
37623778
case _N_class:
37633779
{ // check for string match
37643780
for (; _First_arg != _Last; ++_First_arg) { // look for starting match
3765-
using _Uelem = typename _RxTraits::_Uelem;
37663781
bool _Found;
3767-
auto _Ch = static_cast<_Uelem>(*_First_arg);
3782+
_Elem _Ch = *_First_arg;
3783+
if (_Sflags & regex_constants::icase) {
3784+
_Ch = _Traits.translate_nocase(_Ch);
3785+
} else if (_Sflags & regex_constants::collate) {
3786+
_Ch = _Traits.translate(_Ch);
3787+
}
3788+
const auto _UCh = static_cast<typename _RxTraits::_Uelem>(_Ch);
3789+
37683790
_Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Nx);
37693791
_It _Next = _First_arg;
37703792
++_Next;
37713793

3772-
if (_Sflags & regex_constants::icase) {
3773-
_Ch = static_cast<_Uelem>(_Traits.translate_nocase(static_cast<_Elem>(_Ch)));
3774-
}
3775-
3776-
if (_Node->_Coll && _Lookup_coll(_First_arg, _Next, _Node->_Coll) != _First_arg) {
3794+
if (_Node->_Coll && _STD _Lookup_coll(_First_arg, _Next, _Node->_Coll) != _First_arg) {
37773795
_Found = true;
37783796
} else if (_Node->_Ranges
3779-
&& (_Lookup_range(static_cast<_Uelem>(_Sflags & regex_constants::collate
3780-
? _Traits.translate(static_cast<_Elem>(_Ch))
3781-
: static_cast<_Elem>(_Ch)),
3782-
_Node->_Ranges))) {
3797+
&& (_Sflags & regex_constants::collate
3798+
? _STD _Lookup_collating_range(_Ch, _Node->_Ranges, _Traits)
3799+
: _STD _Lookup_range(_UCh, _Node->_Ranges))) {
37833800
_Found = true;
3784-
} else if (_Ch < _Bmp_max) {
3785-
_Found = _Node->_Small && _Node->_Small->_Find(_Ch);
3801+
} else if (_UCh < _Bmp_max) {
3802+
_Found = _Node->_Small && _Node->_Small->_Find(_UCh);
37863803
} else if (_Node->_Large
37873804
&& _STD find(_Node->_Large->_Str(), _Node->_Large->_Str() + _Node->_Large->_Size(), _Ch)
37883805
!= _Node->_Large->_Str() + _Node->_Large->_Size()) {
37893806
_Found = true;
3790-
} else if (_Node->_Classes && _Traits.isctype(static_cast<_Elem>(_Ch), _Node->_Classes)) {
3807+
} else if (_Node->_Classes != typename _RxTraits::char_class_type{}
3808+
&& _Traits.isctype(_Ch, _Node->_Classes)) {
37913809
_Found = true;
3792-
} else if (_Node->_Equiv && _Lookup_equiv(_Ch, _Node->_Equiv, _Traits)) {
3810+
} else if (_Node->_Equiv && _STD _Lookup_equiv(_UCh, _Node->_Equiv, _Traits)) {
37933811
_Found = true;
37943812
} else {
37953813
_Found = false;
@@ -3858,7 +3876,7 @@ _BidIt _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Skip(_BidIt _First_arg, _BidIt
38583876
}
38593877

38603878
template <class _FwdIt, class _Elem, class _RxTraits>
3861-
void _Parser<_FwdIt, _Elem, _RxTraits>::_Error(regex_constants::error_type _Code) { // handle error
3879+
[[noreturn]] void _Parser<_FwdIt, _Elem, _RxTraits>::_Error(regex_constants::error_type _Code) { // handle error
38623880
_Xregex_error(_Code);
38633881
}
38643882

@@ -4171,7 +4189,14 @@ void _Parser<_FwdIt, _Elem, _RxTraits>::_ClassRanges() { // check for valid clas
41714189
_Chr2 = _Traits.translate(_Chr2);
41724190
}
41734191

4174-
if (static_cast<typename _RxTraits::_Uelem>(_Chr2) < static_cast<typename _RxTraits::_Uelem>(_Chr1)) {
4192+
if (_Flags & regex_constants::collate) {
4193+
const _Elem* const _Chr1_ptr = _STD addressof(_Chr1);
4194+
const _Elem* const _Chr2_ptr = _STD addressof(_Chr2);
4195+
if (_Traits.transform(_Chr2_ptr, _Chr2_ptr + 1) < _Traits.transform(_Chr1_ptr, _Chr1_ptr + 1)) {
4196+
_Error(regex_constants::error_range);
4197+
}
4198+
} else if (static_cast<typename _RxTraits::_Uelem>(_Chr2)
4199+
< static_cast<typename _RxTraits::_Uelem>(_Chr1)) {
41754200
_Error(regex_constants::error_range);
41764201
}
41774202

tests/std/test.lst

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ tests\GH_004845_logical_operator_traits_with_non_bool_constant
254254
tests\GH_004929_internal_tag_constructors
255255
tests\GH_004930_char_traits_user_specialization
256256
tests\GH_005090_stl_hardening
257+
tests\GH_005204_regex_collating_ranges
257258
tests\GH_005315_destructor_tombstones
258259
tests\LWG2381_num_get_floating_point
259260
tests\LWG2597_complex_branch_cut
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
RUNALL_INCLUDE ..\usual_matrix.lst

0 commit comments

Comments
 (0)