Skip to content

Commit 09c80e2

Browse files
authored
Reland [Clang] Deprecate __is_trivially_relocatable (#139061)
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 #127636. However, having multiple relocatable traits would be confusing in the long run, so we deprecate the old trait. As discussed in #127636 `__builtin_is_cpp_trivially_relocatable` should be used instead.
1 parent 0beb2f5 commit 09c80e2

File tree

7 files changed

+141
-52
lines changed

7 files changed

+141
-52
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
@@ -581,6 +581,15 @@ Bug Fixes to Compiler Builtins
581581
- ``__has_unique_object_representations(Incomplete[])`` is no longer accepted, per
582582
`LWG4113 <https://cplusplus.github.io/LWG/issue4113>`_.
583583

584+
- ``__builtin_is_cpp_trivially_relocatable``, ``__builtin_is_replaceable`` and
585+
``__builtin_trivially_relocate`` have been added to support standard C++26 relocation.
586+
587+
- ``__is_trivially_relocatable`` has been deprecated, and uses should be replaced by
588+
``__builtin_is_cpp_trivially_relocatable``.
589+
Note that, it is generally unsafe to ``memcpy`` non-trivially copyable types that
590+
are ``__builtin_is_cpp_trivially_relocatable``. It is recommanded to use
591+
``__builtin_trivially_relocate`` instead.
592+
584593
Bug Fixes to Attribute Support
585594
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
586595
- 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: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
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+
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-scei-ps4 -std=c++11
4+
25

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

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

1823
struct [[clang::trivial_abi]] S0 {
1924
int a;
2025
};
21-
static_assert(__is_trivially_relocatable(S0), "");
26+
static_assert(__is_trivially_relocatable(S0), ""); // expected-warning{{deprecated}}
27+
static_assert(__builtin_is_cpp_trivially_relocatable(S0), "");
2228

2329
struct __attribute__((trivial_abi)) S1 {
2430
int a;
2531
};
26-
static_assert(__is_trivially_relocatable(S1), "");
32+
static_assert(__is_trivially_relocatable(S1), ""); // expected-warning{{deprecated}}
33+
static_assert(__builtin_is_cpp_trivially_relocatable(S1), "");
34+
2735

2836
struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}} expected-note {{is polymorphic}}
2937
virtual void m();
3038
};
31-
static_assert(!__is_trivially_relocatable(S3), "");
39+
static_assert(!__is_trivially_relocatable(S3), ""); // expected-warning{{deprecated}}
40+
static_assert(__builtin_is_cpp_trivially_relocatable(S3), "");
41+
3242

3343
struct S3_2 {
3444
virtual void m();
3545
} __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), "");
46+
static_assert(!__is_trivially_relocatable(S3_2), ""); // expected-warning{{deprecated}}
47+
static_assert(__builtin_is_cpp_trivially_relocatable(S3_2), "");
3748

3849
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}}
3950
S3_3(S3_3 &&);
@@ -43,9 +54,13 @@ struct __attribute__((trivial_abi)) S3_3 { // expected-warning {{'trivial_abi' c
4354
// The ClangABI4OrPS4 calling convention kind passes classes in registers if the
4455
// copy constructor is trivial for calls *or deleted*, while other platforms do
4556
// not accept deleted constructors.
46-
static_assert(__is_trivially_relocatable(S3_3), "");
57+
static_assert(__is_trivially_relocatable(S3_3), ""); // expected-warning{{deprecated}}
58+
static_assert(!__builtin_is_cpp_trivially_relocatable(S3_3), "");
59+
4760
#else
48-
static_assert(!__is_trivially_relocatable(S3_3), "");
61+
static_assert(!__is_trivially_relocatable(S3_3), ""); // expected-warning{{deprecated}}
62+
static_assert(!__builtin_is_cpp_trivially_relocatable(S3_3), "");
63+
4964
#endif
5065

5166
// Diagnose invalid trivial_abi even when the type is templated because it has a non-trivial field.
@@ -54,20 +69,28 @@ struct __attribute__((trivial_abi)) S3_4 { // expected-warning {{'trivial_abi' c
5469
S3_4(S3_4 &&);
5570
S3_2 s32;
5671
};
57-
static_assert(!__is_trivially_relocatable(S3_4<int>), "");
72+
static_assert(!__is_trivially_relocatable(S3_4<int>), ""); // expected-warning{{deprecated}}
73+
static_assert(!__builtin_is_cpp_trivially_relocatable(S3_4<int>), "");
74+
5875

5976
struct S4 {
6077
int a;
6178
};
62-
static_assert(__is_trivially_relocatable(S4), "");
79+
static_assert(__is_trivially_relocatable(S4), ""); // expected-warning{{deprecated}}
80+
static_assert(__builtin_is_cpp_trivially_relocatable(S4), "");
81+
6382

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

6889
struct __attribute__((trivial_abi)) S9 : public S4 {
6990
};
70-
static_assert(__is_trivially_relocatable(S9), "");
91+
static_assert(__is_trivially_relocatable(S9), ""); // expected-warning{{deprecated}}
92+
static_assert(__builtin_is_cpp_trivially_relocatable(S9), "");
93+
7194

7295
struct __attribute__((trivial_abi(1))) S8 { // expected-error {{'trivial_abi' attribute takes no arguments}}
7396
int a;
@@ -80,8 +103,12 @@ struct __attribute__((trivial_abi)) S10 {
80103
};
81104

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

86113
template <class T>
87114
struct S14 {
@@ -93,15 +120,21 @@ struct __attribute__((trivial_abi)) S15 : S14<T> {
93120
};
94121

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

99129
template <class T>
100130
struct __attribute__((trivial_abi)) S16 {
101131
S14<T> a;
102132
};
103-
static_assert(__is_trivially_relocatable(S16<int>), "");
104-
static_assert(__is_trivially_relocatable(S16<S3>), "");
133+
static_assert(__is_trivially_relocatable(S16<int>), ""); // expected-warning{{deprecated}}
134+
static_assert(__builtin_is_cpp_trivially_relocatable(S16<int>), "");
135+
136+
static_assert(__is_trivially_relocatable(S16<S3>), ""); // expected-warning{{deprecated}}
137+
static_assert(__builtin_is_cpp_trivially_relocatable(S16<S3>), "");
105138

106139
S16<int> s16;
107140

@@ -110,62 +143,81 @@ struct __attribute__((trivial_abi)) S17 {
110143
};
111144

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

116153
namespace deletedCopyMoveConstructor {
117154
struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} expected-note {{copy constructors and move constructors are all deleted}}
118155
CopyMoveDeleted(const CopyMoveDeleted &) = delete;
119156
CopyMoveDeleted(CopyMoveDeleted &&) = delete;
120157
};
121158
#ifdef __ORBIS__
122-
static_assert(__is_trivially_relocatable(CopyMoveDeleted), "");
159+
static_assert(__is_trivially_relocatable(CopyMoveDeleted), ""); // expected-warning{{deprecated}}
160+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyMoveDeleted), "");
161+
123162
#else
124-
static_assert(!__is_trivially_relocatable(CopyMoveDeleted), "");
163+
static_assert(!__is_trivially_relocatable(CopyMoveDeleted), ""); // expected-warning{{deprecated}}
164+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyMoveDeleted), "");
165+
125166
#endif
126167

127168
struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
128169
CopyMoveDeleted a;
129170
};
130171
#ifdef __ORBIS__
131-
static_assert(__is_trivially_relocatable(S18), "");
172+
static_assert(__is_trivially_relocatable(S18), ""); // expected-warning{{deprecated}}
173+
static_assert(!__builtin_is_cpp_trivially_relocatable(S18), "");
132174
#else
133-
static_assert(!__is_trivially_relocatable(S18), "");
175+
static_assert(!__is_trivially_relocatable(S18), ""); // expected-warning{{deprecated}}
176+
static_assert(!__builtin_is_cpp_trivially_relocatable(S18), "");
134177
#endif
135178

136179
struct __attribute__((trivial_abi)) CopyDeleted {
137180
CopyDeleted(const CopyDeleted &) = delete;
138181
CopyDeleted(CopyDeleted &&) = default;
139182
};
140183
#if defined(_WIN64) && !defined(__MINGW32__)
141-
static_assert(!__is_trivially_relocatable(CopyDeleted), "");
184+
static_assert(!__is_trivially_relocatable(CopyDeleted), ""); // expected-warning{{deprecated}}
185+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyDeleted), "");
186+
142187
#else
143-
static_assert(__is_trivially_relocatable(CopyDeleted), "");
188+
static_assert(__is_trivially_relocatable(CopyDeleted), ""); // expected-warning{{deprecated}}
189+
static_assert(!__builtin_is_cpp_trivially_relocatable(CopyDeleted), "");
144190
#endif
145191

146192
struct __attribute__((trivial_abi)) MoveDeleted {
147193
MoveDeleted(const MoveDeleted &) = default;
148194
MoveDeleted(MoveDeleted &&) = delete;
149195
};
150-
static_assert(__is_trivially_relocatable(MoveDeleted), "");
151-
196+
static_assert(__is_trivially_relocatable(MoveDeleted), ""); // expected-warning{{deprecated}}
197+
static_assert(!__builtin_is_cpp_trivially_relocatable(MoveDeleted), "");
152198
struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} expected-note {{copy constructors and move constructors are all deleted}}
153199
CopyDeleted a;
154200
MoveDeleted b;
155201
};
156202
#ifdef __ORBIS__
157-
static_assert(__is_trivially_relocatable(S19), "");
203+
static_assert(__is_trivially_relocatable(S19), ""); // expected-warning{{deprecated}}
204+
static_assert(!__builtin_is_cpp_trivially_relocatable(S19), "");
158205
#else
159-
static_assert(!__is_trivially_relocatable(S19), "");
206+
static_assert(!__is_trivially_relocatable(S19), ""); // expected-warning{{deprecated}}
207+
static_assert(!__builtin_is_cpp_trivially_relocatable(S19), "");
160208
#endif
161209

162210
// This is fine since the move constructor isn't deleted.
163211
struct __attribute__((trivial_abi)) S20 {
164212
int &&a; // a member of rvalue reference type deletes the copy constructor.
165213
};
166214
#if defined(_WIN64) && !defined(__MINGW32__)
167-
static_assert(!__is_trivially_relocatable(S20), "");
215+
static_assert(!__is_trivially_relocatable(S20), ""); // expected-warning{{deprecated}}
216+
static_assert(!__builtin_is_cpp_trivially_relocatable(S20), "");
217+
168218
#else
169-
static_assert(__is_trivially_relocatable(S20), "");
219+
static_assert(__is_trivially_relocatable(S20), ""); // expected-warning{{deprecated}}
220+
static_assert(!__builtin_is_cpp_trivially_relocatable(S20), "");
221+
170222
#endif
171223
} // namespace deletedCopyMoveConstructor

0 commit comments

Comments
 (0)