This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Use std::addressof in std::function::target
ClosedPublic

Authored by ldionne on Dec 29 2021, 9:25 AM.

Details

Summary

This guards against hostile overloads of operator&. Thanks to Peter Dimov
for the report.

Diff Detail

Event Timeline

ldionne requested review of this revision.Dec 29 2021, 9:25 AM
ldionne created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 29 2021, 9:25 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Quuxplusone requested changes to this revision.Dec 29 2021, 9:37 AM
Quuxplusone added a subscriber: Quuxplusone.
Quuxplusone added inline comments.
libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/addressof.pass.cpp
21

template<class T> friend void operator&(T) {} to expand its power a bit further.
Or actually, even better, go all out with the traditional ADL-proofing test:

struct Incomplete;
template<class T> struct Holder { T t; };
template<class T> struct Callable {
    int operator()() const { return 1; }
};

int main(int, char**) {
    std::function<int()> f = Callable<Holder<Incomplete>>();
    assert(f() == 1);
    return 0;
}
This revision now requires changes to proceed.Dec 29 2021, 9:37 AM
Mordante accepted this revision as: Mordante.Dec 29 2021, 9:40 AM
Mordante added a subscriber: Mordante.

LGTM except for a minor issue.

libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/addressof.pass.cpp
23

Can you use test/support/operator_hijacker.h's operator_hijacker instead? If not I would like the operator&() to be deleted.

ldionne marked 2 inline comments as done.Dec 29 2021, 9:50 AM
ldionne updated this revision to Diff 396546.Dec 29 2021, 9:50 AM

Address review comments

I don't see the point of having two ADL-proofing tests (robust_against_adl.pass.cpp and the new one), and I wonder why the old robust_against_adl.pass.cpp bothered to test three different cases but you're adding only one new case (like, should there be a matching test for std::function<int()> as well as std::function<void()>?) but anyway this certainly seems code-correct and sufficiently-tested at this point. :)

I don't see the point of having two ADL-proofing tests (robust_against_adl.pass.cpp and the new one), and I wonder why the old robust_against_adl.pass.cpp bothered to test three different cases but you're adding only one new case (like, should there be a matching test for std::function<int()> as well as std::function<void()>?) but anyway this certainly seems code-correct and sufficiently-tested at this point. :)

The added test case in addressof.pass.cpp is not checking for ADL proofing, but really for the specific case of using operator& instead of addressof. For example, the ADL proofing test would pass if we used __f_.__target().operator&(), but the operator hijacking one would not. Since we can't reasonably use .operator&() (other stuff would fail), this is mostly academic, but I think it still makes sense to have a test whose *intent* is specifically to test the reported bug.

Mordante accepted this revision.Jan 2 2022, 8:14 AM
This revision is now accepted and ready to land.Jan 2 2022, 8:14 AM
ldionne updated this revision to Diff 397130.Jan 3 2022, 1:40 PM

Rebase onto main for CI.

ldionne updated this revision to Diff 397147.Jan 3 2022, 2:32 PM

Fix C++03

This revision was automatically updated to reflect the committed changes.