llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

Inconsistent results for `__is_trivially_relocatable` between Clang and Apple Clang

Open dangelog opened this issue 1 year ago • 4 comments

Testcase from Qt:

#include <type_traits>

template <typename T>
inline constexpr bool qIsRelocatable = (std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>)
#if defined(__has_builtin)
#if __has_builtin(__is_trivially_relocatable)
                                       || __is_trivially_relocatable(T)
#endif
#endif
    ;

struct Complex2
{
    Complex2(Complex2 &&);
};
static_assert(!qIsRelocatable<Complex2>);

This works for clang 15.0.0→18.1.0, but the static_assert fails for Apple clang version 15.0.0 (clang-1500.0.40.1).

Could someone confirm that this is Apple clang's fault? A class with a user-defined special member (case in point, not even trivially copyable) and which is not marked in any way (e.g. with [[clang::trivial_abi]]) should not be detected as trivially relocatalble.

dangelog avatar Mar 22 '24 22:03 dangelog

@llvm/issue-subscribers-clang-frontend

Author: Giuseppe D'Angelo (dangelog)

Testcase from Qt:
#include &lt;type_traits&gt;

template &lt;typename T&gt;
inline constexpr bool qIsRelocatable = (std::is_trivially_copyable_v&lt;T&gt; &amp;&amp; std::is_trivially_destructible_v&lt;T&gt;)
#if defined(__has_builtin)
#if __has_builtin(__is_trivially_relocatable)
                                       || __is_trivially_relocatable(T)
#endif
#endif
    ;

struct Complex2
{
    Complex2(Complex2 &amp;&amp;);
};
static_assert(!qIsRelocatable&lt;Complex2&gt;);

This works for clang 15.0.0→18.1.0, but the static_assert fails for Apple clang version 15.0.0 (clang-1500.0.40.1).

Could someone confirm that this is Apple clang's fault? A class with a user-defined special member (case in point, not even trivially copyable) and which is not marked in any way (e.g. with [[clang::trivial_abi]]) should not be detected as trivially relocatalble.

llvmbot avatar Mar 22 '24 23:03 llvmbot

I don't see this one clang trunk or any other version: https://godbolt.org/z/EM1ododMv

CC @Bigcheese @ldionne

shafik avatar Mar 23 '24 02:03 shafik

@dangelog Is __is_trivially_relocatable being used on your version of AppleClang? IOW are you able to reduce to something that doesn't have these ifdefs?

ldionne avatar Mar 23 '24 22:03 ldionne

Sure, if you want a minimal testcase:

struct S { S(S &&); };
static_assert(__has_builtin(__is_trivially_relocatable));
static_assert(!__is_trivially_relocatable(S));

This passes on Clang 18, passes on XCode 14, but fails on XCode 15 (clang-1500.0.40.1) with:

a.cpp:3:1: error: static assertion failed due to requirement '!__is_trivially_relocatable(S)'

dangelog avatar Mar 24 '24 13:03 dangelog

I tried various versions of Apple Clang. The reproducer I used was exactly this:

$ clang++ --version

$ cat <<EOF | clang++ -xc++ - -fsyntax-only -std=c++20
struct S { S(S &&); };
static_assert(__has_builtin(__is_trivially_relocatable), "");
static_assert(!__is_trivially_relocatable(S), "");
EOF
Xcode version AppleClang version Has the builtin? S is trivially relocatable?
14.0.1 Apple clang version 14.0.0 (clang-1400.0.29.102) n/a
14.3.1 Apple clang version 14.0.3 (clang-1403.0.22.14.1) n/a
15.0.1 Apple clang version 15.0.0 (clang-1500.0.40.1) yes
15.3 Apple clang version 15.0.0 (clang-1500.3.9.4) yes

However, LLVM Clang seems to agree that S is not trivially relocatable in all versions: https://godbolt.org/z/csfxPvTY6

ldionne avatar Mar 26 '24 18:03 ldionne

So.. this looks like an AppleClang specific issue to me. I don't know what's different in Clang and AppleClang that causes this, I looked around a bit but couldn't find anything yet. Filed rdar://125426656 internally, stay tuned.

ldionne avatar Mar 26 '24 18:03 ldionne