Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Okay, so I sat with it first (before just bisecting, which will likely find that problem is gone with 2ab06c1). For many hours. There's bad news. The problem seems traceable to the indirection projection. This is an immutable lambda, but still it ostensibly changes during execution (as part of `project_compare`). I really can't decide yet whether that's a miscompilation, or I'm missing some source of UB lurking there. I added a unit test `issue_139` on branch `issue_139`. The unit test does not repro the ASAN diagnostic, but it *does* manifest the source of the UB, where the captured `&proj` reference (originally include/cpp-sort/adapters/indirect_adapter.h:L123) gets clobbered. The good news is you can see this happening. The bad news is it's not just with Clang6. ((In fact with GCC-10 + ASAN it actually reports _AddressSanitizer: stack-buffer-overflow_). What follows is some of the thinking/observations that went into making the repro: ----- - I figured it might have been down to lambda codegen, but rewriting it as a callable struct made no difference. (Omitted from the unit test for brevity). - Next I figured it might be due to some weird codegen issue with empty-element `tuple<>` optimization in `projection_compare` (because replacing the tuple by it's elements **did** remove the symptom). But sketching an "adhoc" projection_compare in terms of `tuple` does **not** display the same symptom. [Included in the repro code in case you want to check] Among the weirder observations (if that's not enough for you) - depending on how I sequence the tests, the first invocation of `projection_compare::compare()` does the right thing (`&proj == projptr`), but a second invocation fails. - depending on whether I phrase taking the address of `proj` as `&proj` or `std::addressof(proj)` can give different diagnostics some of the time: at times ASAN croaked about invoking a member on a null pointer when using `std::addressof`. ¯\\_(ツ)_/¯ - It's weird that this manifested with std_sort only. Then again, the repro case fails with other compilers/clang versions just as well, even though that never tripped ASAN before. I fail to see something wrong with the actual code. Could it really be just... miscompilation? Pretty scary. Maybe I'm just going crazy and the error is right before our eyes. I'd appreciate a second pair of eyes. Meanwhile, I'm sleeping on it. Maybe tomorrow brings fresh ideas. ----- Apparent workarounds: - capturing `proj` by value - replacing `tuple` projection_compare::data by its parts works - perhaps it is gone with 2ab06c1 (I still wish to understand the phenomenon I'm seeing)
- Loading branch information