Unexpected check-libcxx failures on FreeBSD

I'm running this on FreeBSD 11 (stable). It has clang-3.8.0 as the system compiler. LLVM/Clang/et al. compiled without problems, but I'm seeing failures in check-libcxx. Example below.

Does anyone know what the problem may be?

clang version 4.0.0 (http://llvm.org/git/clang.git a85c03256cfc0812e268f5e0f1b804910e75e673) (http://llvm.org/git/llvm.git c95d4ff692323bde64fc8ef45e174b19450779af)
Target: x86_64-unknown-freebsd11.0
Thread model: posix
InstalledDir: /w/c/org/bin
  "/w/c/org/bin/clang-4.0" -cc1 -triple x86_64-unknown-freebsd11.0 -emit-obj -mrelax-all -disable-free -main-file-name minmax_init_list_comp.pass.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -v -v -dwarf-column-info -debugger-tuning=gdb -coverage-notes-file /w/bld/org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/Output/minmax_init_list_comp.pass.cpp.gcno -nostdinc++ -resource-dir /w/c/org/bin/../lib/clang/4.0.0 -include /w/src/llvm.org/projects/libcxx/test/support/nasty_macros.hpp -I /w/src/llvm.org/projects/libcxx/include -I /w/src/llvm.org/projects/libcxx/test/support -D LIBCXX_FILESYSTEM_STATIC_TEST_ROOT=/w/src/llvm.org/projects/libcxx/test/std/experimental/filesystem/Inputs/static_test_env -D LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT=/w/bld/org/projects/libcxx/test/filesystem/Output/dynamic_env -D LIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER=/usr/local/bin/python2.7 /w/src/llvm.org/projects/libcxx/test/support/filesystem_dynamic_test_helper.py -Werror=thread-safety -std=c++1z -fdeprecated-macro -fdebug-compilation-dir /w/src/llvm.org -ferror-limit 19 -fmessage-length 210 -fobjc-runtime=gnustep -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /w/bld/org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/Output/minmax_init_list_comp.pass.cpp.o -x c++ /w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp
clang -cc1 version 4.0.0 based upon LLVM 4.0.0svn default target x86_64-unknown-freebsd11.0
#include "..." search starts here:
#include <...> search starts here:
  /w/src/llvm.org/projects/libcxx/include
  /w/src/llvm.org/projects/libcxx/test/support
  /w/c/org/bin/../lib/clang/4.0.0/include
  /usr/include
End of search list.
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:68:19: error: static_assert expression is not an integral constant expression
     static_assert((std::minmax({1, 2, 3}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/include/algorithm:2823:12: note: non-constexpr constructor 'pair' cannot be used in a constant expression
     return __result;
            ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:68:20: note: in call to 'minmax({&{1, 2, 3}[0], 3}, {{}})'
     static_assert((std::minmax({1, 2, 3}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
                    ^
/w/src/llvm.org/projects/libcxx/include/utility:316:5: note: declared here
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
     ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:69:19: error: static_assert expression is not an integral constant expression
     static_assert((std::minmax({1, 3, 2}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/include/algorithm:2823:12: note: non-constexpr constructor 'pair' cannot be used in a constant expression
     return __result;
            ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:69:20: note: in call to 'minmax({&{1, 3, 2}[0], 3}, {{}})'
     static_assert((std::minmax({1, 3, 2}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
                    ^
/w/src/llvm.org/projects/libcxx/include/utility:316:5: note: declared here
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
     ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:70:19: error: static_assert expression is not an integral constant expression
     static_assert((std::minmax({2, 1, 3}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/include/algorithm:2823:12: note: non-constexpr constructor 'pair' cannot be used in a constant expression
     return __result;
            ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:70:20: note: in call to 'minmax({&{2, 1, 3}[0], 3}, {{}})'
     static_assert((std::minmax({2, 1, 3}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
                    ^
/w/src/llvm.org/projects/libcxx/include/utility:316:5: note: declared here
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
     ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:71:19: error: static_assert expression is not an integral constant expression
     static_assert((std::minmax({2, 3, 1}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/include/algorithm:2823:12: note: non-constexpr constructor 'pair' cannot be used in a constant expression
     return __result;
            ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:71:20: note: in call to 'minmax({&{2, 3, 1}[0], 3}, {{}})'
     static_assert((std::minmax({2, 3, 1}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
                    ^
/w/src/llvm.org/projects/libcxx/include/utility:316:5: note: declared here
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
     ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:72:19: error: static_assert expression is not an integral constant expression
     static_assert((std::minmax({3, 1, 2}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/include/algorithm:2823:12: note: non-constexpr constructor 'pair' cannot be used in a constant expression
     return __result;
            ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:72:20: note: in call to 'minmax({&{3, 1, 2}[0], 3}, {{}})'
     static_assert((std::minmax({3, 1, 2}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
                    ^
/w/src/llvm.org/projects/libcxx/include/utility:316:5: note: declared here
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
     ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:73:19: error: static_assert expression is not an integral constant expression
     static_assert((std::minmax({3, 2, 1}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/include/algorithm:2823:12: note: non-constexpr constructor 'pair' cannot be used in a constant expression
     return __result;
            ^
/w/src/llvm.org/projects/libcxx/test/std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp:73:20: note: in call to 'minmax({&{3, 2, 1}[0], 3}, {{}})'
     static_assert((std::minmax({3, 2, 1}, std::greater<int>()) == std::pair<int, int>(3, 1)), "");
                    ^
/w/src/llvm.org/projects/libcxx/include/utility:316:5: note: declared here
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
     ^
6 errors generated.

-Krzysztof

Does anyone know what the problem may be?

FreeBSD ships std::pair with explicitly defined copy and move constructors as opposed to explicitly defaulted ones. Mistakenly these constructors have not been marked constexpr in C++14.
FreeBSD provides these old constructors is because switching to defaulted copy/move constructors is an ABI break because it makes std::pair non-trivial and changes how it’s passed to functions according to the Itanium ABI.

Fixing this requires either (A) marking the fallback constructors constexpr in C++14, or (B) convincing FreeBSD to take the ABI break.

The easiest and simplistic fix is (A). However my concern with (A) is that the fallback constructors don’t SFINAE away if they are ill-formed. This means that applying constexpr to them could break existing code by causing the eager instantiation of the ill-formed constructors, instantiations that would not occur if the constructors were non-constexpr. For this reason I think fix (B) is more correct, and greatly preferable.

Since we have plenty of time until the next release I’ll go ahead and commit (A) for now, keeping my ear to the ground for breakage.

/Eric

On second thought applying (A) might be ill-advised. Most of the pair tests still fail after applying it in constructs like “std::is_copy_constructible_v<std::pair<NonCopyable, int&&>>”, except now instead of returning the wrong answer the traits cause hard compile errors and template barf.

@Ed, David, and Dimitry The FreeBSD std::pair implementation is fundamentally broken, and there’s not much I think I can do about it. Is there a timeline for making the ABI change in FreeBSD?

/Eric

In my infinite cleverness I think I found a solution which gives both constexpr and non-trivial constructors.

Please take a look at https://reviews.llvm.org/D25389.

/Eric

This patch works very well. The infinite cleverness delivers again! :slight_smile:

There are still some failures left in check-libcxx, but they seem unrelated, except one:

/usr/bin/CC -o /w/bld/org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/Output/trivial_copy_move.pass.cpp.o -x c++ /w/src/llvm.org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp -c -v -Werror=thread-safety -std=c++1z -nostdinc++ -include /w/src/llvm.org/projects/libcxx/test/support/nasty_macros.hpp -I/w/src/llvm.org/projects/libcxx/include -I/w/src/llvm.org/projects/libcxx/test/support -DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="/w/src/llvm.org/projects/libcxx/test/std/experimental/filesystem/Inputs/static_test_env" -DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="/w/bld/org/projects/libcxx/test/filesystem/Output/dynamic_env" -DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="/usr/local/bin/python2.7 /w/src/llvm.org/projects/libcxx/test/support/filesystem_dynamic_test_helper.py" -c

FreeBSD clang version 3.8.0 (tags/RELEASE_380/final 262564) (based on LLVM 3.8.0)
Target: x86_64-unknown-freebsd11.0
Thread model: posix
InstalledDir: /usr/bin
  "/usr/bin/c++" -cc1 -triple x86_64-unknown-freebsd11.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name trivial_copy_move.pass.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -v -dwarf-column-info -debugger-tuning=gdb -coverage-file /w/bld/org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/Output/trivial_copy_move.pass.cpp.o -nostdinc++ -resource-dir /usr/bin/../lib/clang/3.8.0 -include /w/src/llvm.org/projects/libcxx/test/support/nasty_macros.hpp -I /w/src/llvm.org/projects/libcxx/include -I /w/src/llvm.org/projects/libcxx/test/support -D LIBCXX_FILESYSTEM_STATIC_TEST_ROOT=/w/src/llvm.org/projects/libcxx/test/std/experimental/filesystem/Inputs/static_test_env -D LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT=/w/bld/org/projects/libcxx/test/filesystem/Output/dynamic_env -D LIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER=/usr/local/bin/python2.7 /w/src/llvm.org/projects/libcxx/test/support/filesystem_dynamic_test_helper.py -Werror=thread-safety -std=c++1z -fdeprecated-macro -fdebug-compilation-dir /w/src/llvm.org -ferror-limit 19 -fmessage-length 210 -fobjc-runtime=gnustep -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /w/bld/org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/Output/trivial_copy_move.pass.cpp.o -x c++ /w/src/llvm.org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp
clang -cc1 version 3.8.0 based upon LLVM 3.8.0 default target x86_64-unknown-freebsd11.0
#include "..." search starts here:
#include <...> search starts here:
  /w/src/llvm.org/projects/libcxx/include
  /w/src/llvm.org/projects/libcxx/test/support
  /usr/bin/../lib/clang/3.8.0/include
  /usr/include
End of search list.
/w/src/llvm.org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp:35:9: error: static_assert failed ""
         static_assert(std::is_trivially_copy_constructible<P>::value, "");
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp:40:9: error: static_assert failed ""
         static_assert(std::is_trivially_move_constructible<P>::value, "");
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/w/src/llvm.org/projects/libcxx/test/std/utilities/utility/pairs/pairs.pair/trivial_copy_move.pass.cpp:47:9: error: static_assert failed ""
         static_assert(std::is_trivially_move_constructible<P1>::value, "");
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 errors generated.

-Krzysztof

This patch works very well. The infinite cleverness delivers again! :slight_smile:

There are still some failures left in check-libcxx, but they seem
unrelated, except one:

That error is related, but it's not really a problem, the tests just need
to be disabled for FreeBSD.
The standard requires std::pair be a trivial type when its template
argument types are, but as mentioned above
implementing this is ABI breaking.

/Eric

Sorry for slacking off on this. I have now tested D25389, and the number of unexpected test failures is reduced by 20. :slight_smile:

The trivial_copy_move.pass.cpp tests already failed before D25389, and it does not influence them. They should be disabled on FreeBSD for now, indeed.

Thanks for the nice fix!

-Dimitry