Skip to content

Commit 33d7626

Browse files
committed
[Clang] Deprecate __is_trivially_relocatable
The C++26 standard relocatable type traits has slightly different semantics, so we introduced a new ``__builtin_is_cpp_trivially_relocatable`` when implementing trivial relocation in llvm#127636. However, having multiple relocatable traits would be confusing in the long run, so we deprecate the old trait. As discussed in llvm#127636 `__builtin_is_cpp_trivially_relocatable` should be used instead.
1 parent e1fed24 commit 33d7626

File tree

7 files changed

+140
-53
lines changed

7 files changed

+140
-53
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1859,12 +1859,18 @@ The following type trait primitives are supported by Clang. Those traits marked
18591859
* ``__is_trivially_constructible`` (C++, GNU, Microsoft)
18601860
* ``__is_trivially_copyable`` (C++, GNU, Microsoft)
18611861
* ``__is_trivially_destructible`` (C++, MSVC 2013)
1862-
* ``__is_trivially_relocatable`` (Clang): Returns true if moving an object
1862+
* ``__is_trivially_relocatable`` (Clang) (Deprecated,
1863+
use ``__builtin_is_cpp_trivially_relocatable`` instead).
1864+
Returns true if moving an object
18631865
of the given type, and then destroying the source object, is known to be
18641866
functionally equivalent to copying the underlying bytes and then dropping the
18651867
source object on the floor. This is true of trivial types,
18661868
C++26 relocatable types, and types which
18671869
were made trivially relocatable via the ``clang::trivial_abi`` attribute.
1870+
This trait is deprecated and should be replaced by
1871+
``__builtin_is_cpp_trivially_relocatable``. Note however that it is generally
1872+
unsafe to relocate a C++-relocatable type with ``memcpy`` or ``memmove``;
1873+
use ``__builtin_trivially_relocate``.
18681874
* ``__builtin_is_cpp_trivially_relocatable`` (C++): Returns true if an object
18691875
is trivially relocatable, as defined by the C++26 standard [meta.unary.prop].
18701876
Note that when relocating the caller code should ensure that if the object is polymorphic,

clang/docs/ReleaseNotes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,15 @@ Bug Fixes to Compiler Builtins
574574
- ``__has_unique_object_representations(Incomplete[])`` is no longer accepted, per
575575
`LWG4113 <https://cplusplus.github.io/LWG/issue4113>`_.
576576

577+
- ``__builtin_is_cpp_trivially_relocatable``, ``__builtin_is_replaceable`` and
578+
``__builtin_trivially_relocate`` have been added to support standard C++26 relocation.
579+
580+
- ``__is_trivially_relocatable`` has been deprecated, and uses should be replaced by
581+
``__builtin_is_cpp_trivially_relocatable``.
582+
Note that, it is generally unsafe to ``memcpy`` non-trivially copyable types that
583+
are ``__builtin_is_cpp_trivially_relocatable``. It is recommanded to use
584+
``__builtin_trivially_relocate`` instead.
585+
577586
Bug Fixes to Attribute Support
578587
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
579588
- Fixed crash when a parameter to the ``clang::annotate`` attribute evaluates to ``void``. See #GH119125

clang/include/clang/Basic/TokenKinds.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,6 @@ TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBas
544544
#include "clang/Basic/TransformTypeTraits.def"
545545

546546
// Clang-only C++ Type Traits
547-
TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
548547
TYPE_TRAIT_1(__is_trivially_equality_comparable, IsTriviallyEqualityComparable, KEYCXX)
549548
TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX)
550549
TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX)
@@ -556,8 +555,11 @@ TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary
556555
// IsDeducible is only used internally by clang for CTAD implementation and
557556
// is not exposed to users.
558557
TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX)
559-
TYPE_TRAIT_1(__is_bitwise_cloneable, IsBitwiseCloneable, KEYALL)
558+
559+
// __is_trivially_relocatable is deprecated
560560
TYPE_TRAIT_1(__builtin_is_cpp_trivially_relocatable, IsCppTriviallyRelocatable, KEYCXX)
561+
TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
562+
TYPE_TRAIT_1(__is_bitwise_cloneable, IsBitwiseCloneable, KEYALL)
561563
TYPE_TRAIT_1(__builtin_is_replaceable, IsReplaceable, KEYCXX)
562564
TYPE_TRAIT_1(__builtin_structured_binding_size, StructuredBindingSize, KEYCXX)
563565

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6449,6 +6449,9 @@ void DiagnoseBuiltinDeprecation(Sema& S, TypeTrait Kind,
64496449
case UTT_HasTrivialDestructor:
64506450
Replacement = UTT_IsTriviallyDestructible;
64516451
break;
6452+
case UTT_IsTriviallyRelocatable:
6453+
Replacement = clang::UTT_IsCppTriviallyRelocatable;
6454+
break;
64526455
default:
64536456
return;
64546457
}
Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2+
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-windows-msvc -std=c++11
3+
24

35
void __attribute__((trivial_abi)) foo(); // expected-warning {{'trivial_abi' attribute only applies to classes}}
46

@@ -10,30 +12,38 @@ class __attribute__((trivial_abi)) a { a(a &&); };
1012
// (And it is only trivially relocatable, currently, if it is trivial for calls.)
1113
// In this case, it is suppressed by an explicitly defined move constructor.
1214
// Similar concerns apply to later tests that have #if defined(_WIN64) && !defined(__MINGW32__)
13-
static_assert(!__is_trivially_relocatable(a<int>), "");
15+
static_assert(!__is_trivially_relocatable(a<int>), ""); // expected-warning{{deprecated}}
16+
static_assert(!__builtin_is_cpp_trivially_relocatable(a<int>), "");
1417
#else
15-
static_assert(__is_trivially_relocatable(a<int>), "");
18+
static_assert(__is_trivially_relocatable(a<int>), ""); // expected-warning{{deprecated}}
19+
static_assert(!__builtin_is_cpp_trivially_relocatable(a<int>), "");
1620
#endif
1721

1822
struct [[clang::trivial_abi]] S0 {
1923
int a;
2024
};
21-
static_assert(__is_trivially_relocatable(S0), "");
25+
static_assert(__is_trivially_relocatable(S0), ""); // expected-warning{{deprecated}}
26+
static_assert(__builtin_is_cpp_trivially_relocatable(S0), "");
2227

2328
struct __attribute__((trivial_abi)) S1 {
2429
int a;
2530
};
26-
static_assert(__is_trivially_relocatable(S1), "");
31+
static_assert(__is_trivially_relocatable(S1), ""); // expected-warning{{deprecated}}
32+
static_assert(__builtin_is_cpp_trivially_relocatable(S1), "");
33+
2734

2835
struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}} expected-note {{is polymorphic}}
2936
virtual void m();
3037
};
31-
static_assert(!__is_trivially_relocatable(S3), "");
38+
static_assert(!__is_trivially_relocatable(S3), ""); // expected-warning{{deprecated}}
39+
static_assert(__builtin_is_cpp_trivially_relocatable(S3), "");
40+
3241

3342
struct S3_2 {
3443
virtual void m();
3544
} __attribute__((trivial_abi)); // expected-warning {{'trivial_abi' cannot be applied to 'S3_2'}} expected-note {{is polymorphic}}
36-
static_assert(!__is_trivially_relocatable(S3_2), "");
45+
static_assert(!__is_trivially_relocatable(S3_2), ""); // expected-warning{{deprecated}}
46+
static_assert(__builtin_is_cpp_trivially_relocatable(S3_2), "");
3747

3848
struct __attribute__((trivial_abi)) S3_3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3_3'}} expected-note {{has a field of a non-trivial class type}}
3949
S3_3(S3_3 &&);
@@ -43,9 +53,13 @@ struct __attribute__((trivial_abi)) S3_3 { // expected-warning {{'trivial_abi' c
4353
// The ClangABI4OrPS4 calling convention kind passes classes in registers if the
4454
// copy constructor is trivial for calls *or deleted*, while other platforms do
4555
// not accept deleted constructors.
46-
static_assert(__is_trivially_relocatable(S3_3), "");
56+
static_assert(__is_trivially_relocatable(S3_3), ""); // expected-warning{{deprecated}}
57+
static_assert(__builtin_is_cpp_trivially_relocatable(S3_3), "");
58+
4759
#else
48-
static_assert(!__is_trivially_relocatable(S3_3), "");
60+
static_assert(!__is_trivially_relocatable(S3_3), ""); // expected-warning{{deprecated}}
61+
static_assert(!__builtin_is_cpp_trivially_relocatable(S3_3), "");
62+
4963
#endif
5064

5165
// Diagnose invalid trivial_abi even when the type is templated because it has a non-trivial field.
@@ -54,20 +68,28 @@ struct __attribute__((trivial_abi)) S3_4 { // expected-warning {{'trivial_abi' c
5468
S3_4(S3_4 &&);
5569
S3_2 s32;
5670
};
57-
static_assert(!__is_trivially_relocatable(S3_4<int>), "");
71+
static_assert(!__is_trivially_relocatable(S3_4<int>), ""); // expected-warning{{deprecated}}
72+
static_assert(!__builtin_is_cpp_trivially_relocatable(S3_4<int>), "");
73+
5874

5975
struct S4 {
6076
int a;
6177
};
62-
static_assert(__is_trivially_relocatable(S4), "");
78+
static_assert(__is_trivially_relocatable(S4), ""); // expected-warning{{deprecated}}
79+
static_assert(__builtin_is_cpp_trivially_relocatable(S4), "");
80+
6381

6482
struct __attribute__((trivial_abi)) S5 : public virtual S4 { // expected-warning {{'trivial_abi' cannot be applied to 'S5'}} expected-note {{has a virtual base}}
6583
};
66-
static_assert(!__is_trivially_relocatable(S5), "");
84+
static_assert(!__is_trivially_relocatable(S5), ""); // expected-warning{{deprecated}}
85+
static_assert(!__builtin_is_cpp_trivially_relocatable(S5), "");
86+
6787

6888
struct __attribute__((trivial_abi)) S9 : public S4 {
6989
};
70-
static_assert(__is_trivially_relocatable(S9), "");
90+
static_assert(__is_trivially_relocatable(S9), ""); // expected-warning{{deprecated}}
91+
static_assert(__builtin_is_cpp_trivially_relocatable(S9), "");
92+
7193

7294
struct __attribute__((trivial_abi(1))) S8 { // expected-error {{'trivial_abi' attribute takes no arguments}}
7395
int a;
@@ -80,8 +102,12 @@ struct __attribute__((trivial_abi)) S10 {
80102
};
81103

82104
S10<int *> p1;
83-
static_assert(__is_trivially_relocatable(S10<int>), "");
84-
static_assert(__is_trivially_relocatable(S10<S3>), "");
105+
static_assert(__is_trivially_relocatable(S10<int>), ""); // expected-warning{{deprecated}}
106+
static_assert(__builtin_is_cpp_trivially_relocatable(S10<int>), "");
107+
108+
static_assert(__is_trivially_relocatable(S10<S3>), ""); // expected-warning{{deprecated}}
109+
static_assert(__builtin_is_cpp_trivially_relocatable(S10<S3>), "");
110+
85111

86112
template <class T>
87113
struct S14 {
@@ -93,15 +119,21 @@ struct __attribute__((trivial_abi)) S15 : S14<T> {
93119
};
94120

95121
S15<int> s15;
96-
static_assert(__is_trivially_relocatable(S15<int>), "");
97-
static_assert(__is_trivially_relocatable(S15<S3>), "");
122+
static_assert(__is_trivially_relocatable(S15<int>), ""); // expected-warning{{deprecated}}
123+
static_assert(__builtin_is_cpp_trivially_relocatable(S15<int>), "");
124+
125+
static_assert(__is_trivially_relocatable(S15<S3>), ""); // expected-warning{{deprecated}}
126+
static_assert(__builtin_is_cpp_trivially_relocatable(S15<S3>), "");
98127

99128
template <class T>
100129
struct __attribute__((trivial_abi)) S16 {
101130
S14<T> a;
102131
};
103-
static_assert(__is_trivially_relocatable(S16<int>), "");
104-
static_assert(__is_trivially_relocatable(S16<S3>), "");
132+
static_assert(__is_trivially_relocatable(S16<int>), ""); // expected-warning{{deprecated}}
133+
static_assert(__builtin_is_cpp_trivially_relocatable(S16<int>), "");
134+
135+
static_assert(__is_trivially_relocatable(S16<S3>), ""); // expected-warning{{deprecated}}
136+
static_assert(__builtin_is_cpp_trivially_relocatable(S16<S3>), "");
105137

106138
S16<int> s16;
107139

@@ -110,62 +142,80 @@ struct __attribute__((trivial_abi)) S17 {
110142
};
111143

112144
S17<int> s17;
113-
static_assert(__is_trivially_relocatable(S17<int>), "");
114-
static_assert(__is_trivially_relocatable(S17<S3>), "");
145+
static_assert(__is_trivially_relocatable(S17<int>), ""); // expected-warning{{deprecated}}
146+
static_assert(__builtin_is_cpp_trivially_relocatable(S17<int>), "");
147+
148+
static_assert(__is_trivially_relocatable(S17<S3>), ""); // expected-warning{{deprecated}}
149+
static_assert(__builtin_is_cpp_trivially_relocatable(S17<S3>), "");
150+
115151

116152
namespace deletedCopyMoveConstructor {
117153
struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} expected-note {{copy constructors and move constructors are all deleted}}
118154
CopyMoveDeleted(const CopyMoveDeleted &) = delete;
119155
CopyMoveDeleted(CopyMoveDeleted &&) = delete;
120156
};
121157
#ifdef __ORBIS__
122-
static_assert(__is_trivially_relocatable(CopyMoveDeleted), "");
158+
static_assert(__is_trivially_relocatable(CopyMoveDeleted), ""); // expected-warning{{deprecated}}
159+
static_assert(__builtin_is_cpp_trivially_relocatable(CopyMoveDeleted), "");
160+
123161
#else
124-
static_assert(!__is_trivially_relocatable(CopyMoveDeleted), "");
162+
static_assert(!__is_trivially_relocatable(CopyMoveDeleted), ""); // expected-warning{{deprecated}}
163+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyMoveDeleted), "");
164+
125165
#endif
126166

127167
struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
128168
CopyMoveDeleted a;
129169
};
130170
#ifdef __ORBIS__
131-
static_assert(__is_trivially_relocatable(S18), "");
171+
static_assert(__is_trivially_relocatable(S18), ""); // expected-warning{{deprecated}}
172+
static_assert(__builtin_is_cpp_trivially_relocatable(S18), "");
132173
#else
133-
static_assert(!__is_trivially_relocatable(S18), "");
174+
static_assert(!__is_trivially_relocatable(S18), ""); // expected-warning{{deprecated}}
175+
static_assert(!__builtin_is_cpp_trivially_relocatable(S18), "");
134176
#endif
135177

136178
struct __attribute__((trivial_abi)) CopyDeleted {
137179
CopyDeleted(const CopyDeleted &) = delete;
138180
CopyDeleted(CopyDeleted &&) = default;
139181
};
140182
#if defined(_WIN64) && !defined(__MINGW32__)
141-
static_assert(!__is_trivially_relocatable(CopyDeleted), "");
183+
static_assert(!__is_trivially_relocatable(CopyDeleted), ""); // expected-warning{{deprecated}}
184+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyDeleted), "");
185+
142186
#else
143-
static_assert(__is_trivially_relocatable(CopyDeleted), "");
187+
static_assert(__is_trivially_relocatable(CopyDeleted), ""); // expected-warning{{deprecated}}
188+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyDeleted), "");
144189
#endif
145190

146191
struct __attribute__((trivial_abi)) MoveDeleted {
147192
MoveDeleted(const MoveDeleted &) = default;
148193
MoveDeleted(MoveDeleted &&) = delete;
149194
};
150-
static_assert(__is_trivially_relocatable(MoveDeleted), "");
151-
195+
static_assert(__is_trivially_relocatable(MoveDeleted), ""); // expected-warning{{deprecated}}
196+
static_assert(!__builtin_is_cpp_trivially_relocatable(MoveDeleted), "");
152197
struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} expected-note {{copy constructors and move constructors are all deleted}}
153198
CopyDeleted a;
154199
MoveDeleted b;
155200
};
156201
#ifdef __ORBIS__
157-
static_assert(__is_trivially_relocatable(S19), "");
158-
#else
159-
static_assert(!__is_trivially_relocatable(S19), "");
202+
static_assert(__is_trivially_relocatable(S19), ""); // expected-warning{{deprecated}}
203+
static_assert(__builtin_is_cpp_trivially_relocatable(S19), "");
204+
static_assert(!__is_trivially_relocatable(S19), ""); // expected-warning{{deprecated}}
205+
static_assert(!__builtin_is_cpp_trivially_relocatable(S19), "");
160206
#endif
161207

162208
// This is fine since the move constructor isn't deleted.
163209
struct __attribute__((trivial_abi)) S20 {
164210
int &&a; // a member of rvalue reference type deletes the copy constructor.
165211
};
166212
#if defined(_WIN64) && !defined(__MINGW32__)
167-
static_assert(!__is_trivially_relocatable(S20), "");
213+
static_assert(!__is_trivially_relocatable(S20), ""); // expected-warning{{deprecated}}
214+
static_assert(!__builtin_is_cpp_trivially_relocatable(S20), "");
215+
168216
#else
169-
static_assert(__is_trivially_relocatable(S20), "");
217+
static_assert(__is_trivially_relocatable(S20), ""); // expected-warning{{deprecated}}
218+
static_assert(!__builtin_is_cpp_trivially_relocatable(S20), "");
219+
170220
#endif
171221
} // namespace deletedCopyMoveConstructor

0 commit comments

Comments
 (0)