-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[libc++] Fix num_get base parsing #170460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions h,cpp -- libcxx/include/__locale_dir/num.h libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp --diff_from_common_commit
View the diff from clang-format here.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 45b034833..db9c4585d 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,101 +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;
+ { // 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 + 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 + 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);
+ }
+ {
+ 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);
+ 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;
+ { // 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 == 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 + 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);
+ }
+ {
+ 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);
+ 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;
}
|
|
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesFull diff: https://github.com/llvm/llvm-project/pull/170460.diff 2 Files Affected:
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;
}
|
|
This fixes the problems we've seen so far. Thank you! |
alexfh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG. Thanks! This resolves the problems for us.
This fixes two bugs reported in llvm#121795 and adds regression tests. Specifically, these bugs are in the base detection mechanism. The first bug is that the out parameter isn't set when the stream only contains zero and after that is the end of the stream. The second one is that we don't consider `0` to be a number, and instead we only parse it as the start of an octal literal.
This fixes two bugs reported in #121795 and adds regression tests. Specifically, these bugs are in the base detection mechanism. The first bug is that the out parameter isn't set when the stream only contains zero and after that is the end of the stream. The second one is that we don't consider
0to be a number, and instead we only parse it as the start of an octal literal.