This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Avoid triggering warnings for implicit conversion
ClosedPublic

Authored by ldionne on Jul 20 2021, 8:46 AM.

Details

Summary

This started as fixing a typo in a ADDITIONAL_COMPILE_FLAGS directive
which turned out to uncover a few places where we warned about signedness
changes.

As a fly-by fix, this updates the various __advance overloads
for style consistency.

Diff Detail

Event Timeline

ldionne requested review of this revision.Jul 20 2021, 8:46 AM
ldionne created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptJul 20 2021, 8:46 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
ldionne updated this revision to Diff 360283.Jul 20 2021, 2:46 PM
ldionne retitled this revision from [libc++][NFCI] Fix typo in ADDITIONAL_COMPILE_FLAGS markup to [libc++] Don't perform implicit conversion in advance, take 2.
ldionne edited the summary of this revision. (Show Details)

Repurpose the patch -- the main purpose is now fixing std::advance

Quuxplusone requested changes to this revision.Jul 20 2021, 3:10 PM
Quuxplusone added a subscriber: Quuxplusone.
Quuxplusone added inline comments.
libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp
68–72

I don't see anything in https://eel.is/c++draft/iterator.operations that forbids vendors from doing a conversion to iter_difference_t here. (In fact, both std::next and std::ranges::advance require that conversion, so it shouldn't be surprising if std::advance also does it.)
The Standard says only: "Increments i by n if n is non-negative, and decrements i by -n otherwise." Presumably the intention is to use the iterator's operator+= to do that (although the Standard doesn't say); and the iterator is not guaranteed to provide any satisfactory operator+= except the one taking iter_difference_t. So if you're trying to pass Distance unmodified to operator+=, you're not always going to be able to satisfy the Standard's behavioral requirement here. The only way to guarantee that you're getting a valid, concept-semantic-modeling overload of operator+= is to do the conversion first.

This is https://cplusplus.github.io/LWG/issue3439 ; see also https://cplusplus.github.io/LWG/issue3213 which mandates convertible-to-integral for Size.

TLDR: I think this patch is misguided. If anything, we should be testing for

template<class Distance>
struct DistanceChecker {
    ~~~
    TEST_CONSTEXPR_CXX17 DistanceChecker& operator+=(difference_type) { ~~~ }
    TEST_CONSTEXPR_CXX17 DistanceChecker& operator+=(int) = delete;
}
std::advance(it, 1);  // should advance by difference_type(1), not int(1)

However, in practice I would recommend not testing for that, either; that kind of iterator type seems to violate common sense re the proper design of overload sets.

This revision now requires changes to proceed.Jul 20 2021, 3:10 PM
ldionne marked an inline comment as done.Jul 21 2021, 5:59 AM
ldionne added inline comments.
libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp
68–72

Hmm, okay, I guess I am swayed. I'll repurpose this patch again to only remove the -Wsign-conversion warnings.

ldionne updated this revision to Diff 360413.Jul 21 2021, 5:59 AM
ldionne marked an inline comment as done.
ldionne retitled this revision from [libc++] Don't perform implicit conversion in advance, take 2 to [libc++] Avoid triggering warnings for implicit conversion.
ldionne edited the summary of this revision. (Show Details)

Repurpose.

LGTM at this point if buildkite is happy (which it seems it's not, yet).
If you think the advance stuff needs more thought/discussion, then feel free to ship the hash and tuple pieces, which seem utterly non-controversial, just to get them out of the way.

libcxx/include/__iterator/advance.h
60–61 ↗(On Diff #360413)

_IntegralDistance is used only once. If you want, you could roll these back up into a single parameter

class = _EnableIf<is_integral<decltype(_VSTD::__convert_to_integral(declval<_Distance>()))>::value>
ldionne added inline comments.Jul 22 2021, 11:28 AM
libcxx/include/__iterator/advance.h
60–61 ↗(On Diff #360413)

I think I'll leave it as-is, I find it easier to read.

ldionne updated this revision to Diff 360900.Jul 22 2021, 11:28 AM

Fix CI (hopefully).

ldionne accepted this revision as: Restricted Project.Jul 23 2021, 7:52 AM
This revision was not accepted when it landed; it landed in state Needs Review.Jul 23 2021, 7:53 AM
This revision was automatically updated to reflect the committed changes.

@ldionne: Serendipitously, @jwakely just alerted me to LWG's Tentatively Ready on @tcanens' paper P2393R0 "Cleaning up integer-class types", which specifically mandates (the effect of) an explicit cast from decltype(n) to iter_difference_t<I> every time the library clauses talk about i + n or i - n. See the added section marked '?', in green.
The state-of-trunk after D106372 seems pretty darn close to what's about to be mandated — and in particular, D106372 didn't make things worse. :) Good!