basic_ios delays initialization of __fill_ to widen(' ') until fill() is called. But, fill(char_type) is missing this logic, so the fill character does not get initialized to whitespace if fill(char_type) is called first. This patch adds this logic to fill(char_type).
Details
- Reviewers
daltenty xingxue ldionne • Quuxplusone - Group Reviewers
Restricted Project - Commits
- rG3e8771917729: [libc++] Fix initialization of __fill_
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
libcxx/include/ios | ||
---|---|---|
681 | Changing the size of basic_ios is a non-starter, because ABI. | |
libcxx/test/std/input.output/iostreams.base/ios/basic.ios.members/fill_init.pass.cpp | ||
26 ↗ | (On Diff #412164) | If this 0 means a pointer, please prefer nullptr instead. |
36 ↗ | (On Diff #412164) | eof() is not a character, so you can't fill with it. AFAIK, this line has UB. |
libcxx/include/ios | ||
---|---|---|
681 | This is ABI-breaking. I don't think we can fix that part of the bug. Do you know how other implementations do it? Do they use a boolean flag similarly to this? That seems like a rather strange implementation requirement to me -- is it possible that all implementations have the same bug? In that case, perhaps we only need a LWG issue to actually standardize what all implementations do, but I'm just speculating. |
Thanks for the review. I removed the flag and new test. I modified the existing test for fill(char_type) to test the initialization of the fill character on the first call. This test was passing because it called fill() first in the assert. Calling fill() first is already tested in fill.pass.cpp
LGTM now! but let's wait for @ldionne to re-examine it.
libcxx/include/ios | ||
---|---|---|
784–786 | Ah, this looks vastly better! char_type __r = traits_type::eq_int_type(__fill_, traits_type::eof()) ? widen(' ') : __fill_; so we're not overwriting __fill_ twice; but I see that what you've done here is consistent with lines 774-775 above, so IMHO it's fine as-is. |
LGTM if this passes CI. I have a hunch we might need some XFAIL: apple-macosxFOO markup if this ends up being instantiated in the dylib. If not, ship it.
Thanks for fixing!
Changing the size of basic_ios is a non-starter, because ABI.
However, we don't need a separate bool for this. Notice that eof() by definition is not equal to any possible value of char_type, so if __fill_ == traits_type::eof() then we can be 100% sure that it hasn't been set by the user. Certainly the scenario you describe in the PR summary — "the user sets a value for the fill character that happens to equal traits_type::eof()" — cannot possibly happen.