Bug 264877 - clang-14 fails with unreasonable cryptic message on a valid C++ code
Summary: clang-14 fails with unreasonable cryptic message on a valid C++ code
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 13.1-STABLE
Hardware: Any Any
: --- Affects Only Me
Assignee: Dimitry Andric
URL: https://github.com/llvm/llvm-project/...
Keywords:
Depends on:
Blocks:
 
Reported: 2022-06-24 19:12 UTC by Yuri Victorovich
Modified: 2024-01-21 12:45 UTC (History)
3 users (show)

See Also:


Attachments
test.cpp (245 bytes, text/plain)
2022-06-24 19:12 UTC, Yuri Victorovich
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Yuri Victorovich freebsd_committer freebsd_triage 2022-06-24 19:12:11 UTC
Created attachment 234920 [details]
test.cpp

The attached testcase fails in clang-14, but not in clang-13 and earlier.

Failure message:
> $ clang++14 test.cpp
> ld: error: undefined hidden symbol: std::__1::enable_if<(is_move_constructible<int>::value) && (is_move_assignable<int>::value), void>::type std::__1::swap<int>(int&, int&)
> >>> referenced by test.cpp
> >>>               /tmp/test-e3003a.o:(main)
> clang-14: error: linker command failed with exit code 1 (use -v to see invocation)



'#include <stdexcept>' is not a proper header for std::swap, so a correct outcome should be one of these two:
* fail to find std::swap -- error: no member named 'swap' in namespace 'std'
* succeed (through proxy header inclusion)

The above error message is incorrect and irrelevant. It indicates a problem in the toolchain.

This is a regression in clang-14.

The problem was discovered due to a failure in science/helfem on 14-CURRENT.
Comment 1 Mark Millard 2022-06-24 20:05:19 UTC
Is this just the LLVM vintage (14), also applying to the same
vintage but outside FreeBSD contexts?

If yes, it would seem to need to be submitted upstream (LLVM)
and FreeBSD would later pick up whatever LLVM does about it.

If this is somehow FreeBSD-only, any clue about how?
Comment 2 Dimitry Andric freebsd_committer freebsd_triage 2022-06-24 20:41:41 UTC
I'm inclined to say "you're holding it wrong" here, but this discussion should really be taken upstream.

Previously, when only including <stdexcept>, you were just lucky that the swap definition was pulled in transitively via <type_traits> (and that was also completely by accident), and it seemed to sort-of work.

At some point upstream committed https://github.com/llvm/llvm-project/commit/6adbc83ee9e46b476e0f75d5671c3a21f675a936:

commit 6adbc83ee9e46b476e0f75d5671c3a21f675a936
Author: Christopher Di Bella <cjdb@google.com>
Date:   Sat Jun 5 02:47:47 2021 +0000

    [libcxx][modularisation] moves <utility> content out of <type_traits>

    Moves:

    * `std::move`, `std::forward`, `std::declval`, and `std::swap` into
      `__utility/${FUNCTION_NAME}`.
    * `std::swap_ranges` and `std::iter_swap` into
      `__algorithm/${FUNCTION_NAME}`

    Differential Revision: https://reviews.llvm.org/D103734

This moved stuff that should really be in <utility>, such as swap() into more modular headers, and it had the side effect of only leaving a partial swap declaration in <type_traits> that is explicitly *not* exposed (via the _LIBCPP_INLINE_VISIBILITY macro):

template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR_AFTER_CXX17 __swap_result_t<_Tp>
swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value &&
                                    is_nothrow_move_assignable<_Tp>::value);

I am unsure why this declaration has been left in, though. If I simply comment it out, the compile error for your test case at least becomes a lot clearer:

bug264877/test.cpp:9:7: error: no member named 'swap' in namespace 'std'
        std::swap(X1, X2);
        ~~~~~^

However, the decltype of swap() is used in a few macros after that, so completely removing it might not be the best course of action.
Comment 3 Dimitry Andric freebsd_committer freebsd_triage 2022-06-24 21:03:07 UTC
Reported upstream: https://github.com/llvm/llvm-project/issues/56206
Comment 4 Mark Linimon freebsd_committer freebsd_triage 2024-01-20 22:12:14 UTC
(In reply to Dimitry Andric from comment #3)
I note that the upstream issue is still open as of 20240120.
Comment 5 Dimitry Andric freebsd_committer freebsd_triage 2024-01-21 12:45:46 UTC
(In reply to Mark Linimon from comment #4)
Yeah it's still the same with clang + lib++ 18:

$ cc -v
FreeBSD clang version 18.0.0git (https://github.com/llvm/llvm-project.git llvmorg-18-init-16864-g3b3ee1f53424)
Target: x86_64-unknown-freebsd15.0
Thread model: posix
InstalledDir: /usr/bin

$ c++ -O2 -pipe  test-stdexcept.cpp  -o test-stdexcept
ld: error: undefined hidden symbol: std::__1::enable_if<is_move_constructible<int>::value && is_move_assignable<int>::value, void>::type std::__1::swap[abi:se180000]<int>(int&, int&)
>>> referenced by test-stdexcept.cpp
>>>               /home/dim/tmp/test-stdexcept-3a5a3e.o:(main)
c++: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1