[libcxx-commits] [libcxx] [libc++] Fix num_get base parsing (PR #170460)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Dec 3 02:48:17 PST 2025
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/170460
None
>From c2ff701fe3d63e75ec56f4a63a18cfdc32c91648 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 3 Dec 2025 11:47:59 +0100
Subject: [PATCH] [libc++] Fix num_get base parsing
---
libcxx/include/__locale_dir/num.h | 2 +
.../facet.num.get.members/get_long.pass.cpp | 96 +++++++++++++++++++
2 files changed, 98 insertions(+)
diff --git a/libcxx/include/__locale_dir/num.h b/libcxx/include/__locale_dir/num.h
index 98b8eb0c600f5..b7ea02e7cb7f7 100644
--- a/libcxx/include/__locale_dir/num.h
+++ b/libcxx/include/__locale_dir/num.h
@@ -436,6 +436,7 @@ class num_get : public locale::facet, private __num_get<_CharT> {
++__first;
if (__first == __last) {
__err |= ios_base::eofbit;
+ __v = 0;
return __first;
}
// __c2 == 'x' || __c2 == 'X'
@@ -444,6 +445,7 @@ class num_get : public locale::facet, private __num_get<_CharT> {
++__first;
} else {
__base = 8;
+ __parsed_num = true; // We only swallowed '0', so we've started to parse a number
}
} else {
__base = 10;
diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp
index a110aae2db11b..45b034833fecc 100644
--- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp
@@ -670,5 +670,101 @@ int main(int, char**)
assert(v == std::numeric_limits<long>::min());
}
+ { // Check that auto-detection of the base works properly
+ ios.flags(ios.flags() & ~std::ios::basefield);
+ { // zeroes
+ {
+ v = -1;
+ const char str[] = "0";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 1), ios, err, v);
+ assert(base(iter) == str + 1);
+ assert(err == ios.eofbit);
+ assert(v == 0);
+ }
+ {
+ v = -1;
+ const char str[] = "00";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
+ assert(base(iter) == str + 2);
+ assert(err == ios.eofbit);
+ assert(v == 0);
+ }
+ {
+ v = -1;
+ const char str[] = "0x0";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+ assert(base(iter) == str + 3);
+ assert(err == ios.eofbit);
+ assert(v == 0);
+ }
+ {
+ v = -1;
+ const char str[] = "0X0";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+ assert(base(iter) == str + 3);
+ assert(err == ios.eofbit);
+ assert(v == 0);
+ }
+ }
+ { // first character after base is out of range
+ {
+ v = -1;
+ const char str[] = "08";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
+ assert(base(iter) == str + 1);
+ assert(err == ios.goodbit);
+ assert(v == 0);
+ }
+ {
+ v = -1;
+ const char str[] = "1a";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
+ assert(base(iter) == str + 1);
+ assert(err == ios.goodbit);
+ assert(v == 1);
+ }
+ {
+ v = -1;
+ const char str[] = "0xg";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+ assert(base(iter) == str + 2);
+ assert(err == ios.failbit);
+ assert(v == 0);
+ }
+ {
+ v = -1;
+ const char str[] = "0Xg";
+ std::ios_base::iostate err = ios.goodbit;
+
+ cpp17_input_iterator<const char*> iter =
+ f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+ assert(base(iter) == str + 2);
+ assert(err == ios.failbit);
+ assert(v == 0);
+ }
+ }
+ }
+
return 0;
}
More information about the libcxx-commits
mailing list