<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Mon, Jun 17, 2019 at 12:30 PM Michał Górny via Phabricator <<a href="mailto:reviews@reviews.llvm.org">reviews@reviews.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">mgorny added a comment.<br>
<br>
Marshall, `std/containers/associative/map/map.cons/deduct_const.pass.cpp` test seems to be reliably failing from commit one on both Gentoo Linux and NetBSD. Could you please look at the classical example of totally cryptic C++ error? ;-)<br>
<br>
<a href="http://lab.llvm.org:8011/builders/netbsd-amd64/builds/20/steps/run%20unit%20tests/logs/FAIL%3A%20libc%2B%2B%3A%3Adeduct_const.pass.cpp" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/builders/netbsd-amd64/builds/20/steps/run%20unit%20tests/logs/FAIL%3A%20libc%2B%2B%3A%3Adeduct_const.pass.cpp</a><br></blockquote><div><br></div><div>Well, I can contribute that that's the error that you get when CTAD deduces the wrong thing. Here it's looking at lines 98–100 of deduct_const.pass.cpp</div><div><br></div><div><div>    std::map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, test_allocator<PC>(0, 45));</div><div>    ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::less<int>, test_allocator<PC>>);<br></div></div><div><br></div><div>and deducing the correct value_type for `m`, but it's incorrectly thinking that `test_allocator<PC>` should be used as the <i><b>comparator</b></i> type, not the <i><b>allocator </b></i>type.  This is surprising/incorrect, because if all is going as expected, then CTAD should be considering the deduction guides</div><div><br></div><div><div>template<class _Key, class _Tp, class _Compare = less<typename remove_const<_Key>::type>,</div><div>         class _Allocator = allocator<pair<const _Key, _Tp>>,</div><div>         class = typename enable_if<!__is_allocator<_Compare>::value, void>::type,</div><div>         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type></div><div>map(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare(), _Allocator = _Allocator())</div><div>  -> map<typename remove_const<_Key>::type, _Tp, _Compare, _Allocator>;</div></div><div><br></div><div><div>template<class _Key, class _Tp, class _Allocator,</div><div>         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type></div><div>map(initializer_list<pair<_Key, _Tp>>, _Allocator)</div><div>  -> map<typename remove_const<_Key>::type, _Tp, less<typename remove_const<_Key>::type>, _Allocator>;</div></div><div><br></div><div>CTAD should see that the first guide fails substitution because __is_allocator<test_allocator<PC>>::value (that is, test_allocator should not be taken as the comparator type).</div><div>CTAD should see that the second guide does not fail substitution, so CTAD should unambiguously use the second guide.</div><div><br></div><div>The test passes on OSX using clang trunk.  I don't see any #ifdefs or anything in include/ or in test/support/test_allocator.h that would cause different behavior on Linux or NetBSD.  If you try clang trunk on Linux or NetBSD, do you see different behavior (versus what you see with clang 9.0.0)?</div><div><br></div><div>Unfortunately there is no way to debug CTAD deduction guides — the error messages don't tell you which guides were considered as candidates or which candidate was ultimately chosen.</div><div><br></div><div>–Arthur</div></div></div></div></div></div></div></div>