On Wed, Feb 11, 2026 at 1:21 AM Jonathan Wakely <[email protected]> wrote:
> libstdc++-v3/ChangeLog: > > PR libstdc++/124015 > * testsuite/28_regex/traits/char/lookup_classname.cc: Check for > correct result for unrecognized classname. Check that lookup is > case insensitive. Check that all required classnames are > recognized. Check that icase flag only affects "lower" and > "upper". > * testsuite/28_regex/traits/wchar_t/lookup_classname.cc: > Likewise. > > Reviewed-by: Tomasz Kamiński <[email protected]> > --- > > v2: Extended wchar_t/lookup_classname.cc with the same additions as > char/lookup_classname.cc > > Tested x86_64-linux and aarch64-linux. > LGTM. > > .../28_regex/traits/char/lookup_classname.cc | 66 +++++++++++++++++++ > .../traits/wchar_t/lookup_classname.cc | 65 ++++++++++++++++++ > 2 files changed, 131 insertions(+) > > diff --git > a/libstdc++-v3/testsuite/28_regex/traits/char/lookup_classname.cc > b/libstdc++-v3/testsuite/28_regex/traits/char/lookup_classname.cc > index 0f277bce532c..2e5c1c711818 100644 > --- a/libstdc++-v3/testsuite/28_regex/traits/char/lookup_classname.cc > +++ b/libstdc++-v3/testsuite/28_regex/traits/char/lookup_classname.cc > @@ -28,6 +28,7 @@ > #include <regex> > #include <forward_list> > #include <string.h> > +#include <ctype.h> > #include <testsuite_hooks.h> > > void > @@ -67,10 +68,75 @@ test03() > VERIFY(traits.isctype('C', traits.lookup_classname(s.begin(), s.end(), > true))); > } > > +void > +test04() > +{ > + // Transform "string" into "StRiNg" > + auto mix_case = [](std::string s) { > + int i = 0; > + for (auto& ch : s) > + if (++i % 2) > + ch = toupper(ch); > + return s; > + }; > + > + typedef char CharT; > + typedef std::regex_traits<CharT> traits; > + traits t; > + > + auto lookup = [&t](const std::string& s, bool icase) { > + return t.lookup_classname(s.begin(), s.end(), icase); > + }; > + > + VERIFY( lookup("", false) == 0 ); > + VERIFY( lookup(":::not a valid classname:::", false) == 0 ); > + VERIFY( lookup(":::not a valid classname:::", true) == 0 ); > + VERIFY( lookup("alnu", false) == 0 ); > + VERIFY( lookup("alnumb", false) == 0 ); > + VERIFY( lookup("x", false) == 0 ); > + VERIFY( lookup("di", false) == 0 ); > + VERIFY( lookup("digi", false) == 0 ); > + VERIFY( lookup("digix", false) == 0 ); > + VERIFY( lookup(std::string{"d\0i", 3}, false) == 0 ); > + VERIFY( lookup(std::string{"digit\0", 6}, false) == 0 ); > + VERIFY( lookup(std::string{"digit\0bad", 9}, false) == 0 ); > + > + for (std::string cls : { "alnum", "alpha", "blank", "cntrl", "digit", > + "graph", "lower", "print", "punct", "space", > + "upper", "xdigit", "d", "s", "w" }) > + { > + traits::char_class_type val = lookup(cls, false); > + // val should be non-zero: > + VERIFY( val != 0 ); > + // val is independent of the case of the name, > + // i.e. "alpha" and "ALPHA" and "AlPhA" give same result: > + VERIFY( lookup(mix_case(cls), false) == val ); > + > + // Repeat same checks for icase=true. > + traits::char_class_type ival = lookup(cls, true); > + VERIFY( ival != 0 ); > + VERIFY( lookup(mix_case(cls), true) == ival ); > + > + if (cls == "lower" || cls == "upper") // icase=true should affect > value > + { > + VERIFY( ival != val ); > + VERIFY( ival == lookup("alpha", false) ); > + } > + else > + VERIFY( ival == val ); > + > + if (cls == "d") > + VERIFY( val == lookup("digit", false) ); > + else if (cls == "s") > + VERIFY( val == lookup("space", false) ); > + } > +} > + > int main() > { > test01(); > test02(); > test03(); > + test04(); > return 0; > } > diff --git > a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_classname.cc > b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_classname.cc > index 18e289868a17..36db7bbb949d 100644 > --- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_classname.cc > +++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_classname.cc > @@ -45,8 +45,73 @@ test01() > #undef range > } > > +void > +test04() > +{ > + // Transform "string" into "StRiNg" > + auto mix_case = [](std::wstring s) { > + int i = 0; > + for (auto& ch : s) > + if (++i % 2) > + ch = toupper(ch); > + return s; > + }; > + > + typedef wchar_t CharT; > + typedef std::regex_traits<CharT> traits; > + traits t; > + > + auto lookup = [&t](const std::wstring& s, bool icase) { > + return t.lookup_classname(s.begin(), s.end(), icase); > + }; > + > + VERIFY( lookup(L"", false) == 0 ); > + VERIFY( lookup(L":::not a valid classname:::", false) == 0 ); > + VERIFY( lookup(L":::not a valid classname:::", true) == 0 ); > + VERIFY( lookup(L"alnu", false) == 0 ); > + VERIFY( lookup(L"alnumb", false) == 0 ); > + VERIFY( lookup(L"x", false) == 0 ); > + VERIFY( lookup(L"di", false) == 0 ); > + VERIFY( lookup(L"digi", false) == 0 ); > + VERIFY( lookup(L"digix", false) == 0 ); > + VERIFY( lookup(std::wstring{L"d\0i", 3}, false) == 0 ); > + VERIFY( lookup(std::wstring{L"digit\0", 6}, false) == 0 ); > + VERIFY( lookup(std::wstring{L"digit\0bad", 9}, false) == 0 ); > + > + for (std::wstring cls : { L"alnum", L"alpha", L"blank", L"cntrl", > L"digit", > + L"graph", L"lower", L"print", L"punct", > L"space", > + L"upper", L"xdigit", L"d", L"s", L"w" }) > + { > + traits::char_class_type val = lookup(cls, false); > + // val should be non-zero: > + VERIFY( val != 0 ); > + // val is independent of the case of the name, > + // i.e. "alpha" and "ALPHA" and "AlPhA" give same result: > + VERIFY( lookup(mix_case(cls), false) == val ); > + > + // Repeat same checks for icase=true. > + traits::char_class_type ival = lookup(cls, true); > + VERIFY( ival != 0 ); > + VERIFY( lookup(mix_case(cls), true) == ival ); > + > + if (cls == L"lower" || cls == L"upper") // icase=true should affect > value > + { > + VERIFY( ival != val ); > + VERIFY( ival == lookup(L"alpha", false) ); > + } > + else > + VERIFY( ival == val ); > + > + if (cls == L"d") > + VERIFY( val == lookup(L"digit", false) ); > + else if (cls == L"s") > + VERIFY( val == lookup(L"space", false) ); > + } > +} > + > int main() > { > test01(); > + test04(); > return 0; > } > -- > 2.52.0 > >
