This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Fix initialization of __fill_
ClosedPublic

Authored by Jake-Egan on Mar 1 2022, 10:13 AM.

Details

Summary

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).

Diff Detail

Event Timeline

Jake-Egan requested review of this revision.Mar 1 2022, 10:13 AM
Jake-Egan created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptMar 1 2022, 10:13 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Jake-Egan edited the summary of this revision. (Show Details)Mar 1 2022, 10:18 AM
Jake-Egan added reviewers: daltenty, xingxue.
Jake-Egan updated this revision to Diff 412164.Mar 1 2022, 10:48 AM

Fix indentation.

Quuxplusone added inline comments.
libcxx/include/ios
681

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.

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.

ldionne requested changes to this revision.Mar 1 2022, 11:25 AM
ldionne added a subscriber: ldionne.
ldionne added inline comments.
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.

This revision now requires changes to proceed.Mar 1 2022, 11:25 AM
Jake-Egan updated this revision to Diff 412399.EditedMar 2 2022, 6:39 AM

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

Herald added a project: Restricted Project. · View Herald TranscriptMar 2 2022, 6:39 AM
Jake-Egan edited the summary of this revision. (Show Details)Mar 2 2022, 6:40 AM

LGTM now! but let's wait for @ldionne to re-examine it.

libcxx/include/ios
784–786

Ah, this looks vastly better!
At first I wondered whether these three lines should be replaced with

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.

Jake-Egan updated this revision to Diff 412517.Mar 2 2022, 12:59 PM
Jake-Egan edited the summary of this revision. (Show Details)

Rebase to hopefully fix format check

ldionne accepted this revision.Mar 2 2022, 1:13 PM

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!

This revision is now accepted and ready to land.Mar 2 2022, 1:13 PM
This revision was automatically updated to reflect the committed changes.