-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[Clang][C++26] Remove the notion of replaceability. #172150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
In Kona, WG21 decided to revert trivial relocation (P2786). Given that the notion of replaceability that was introduced at the same time does not appear to be used by clang 21 users, and is less likely to come back, it is easier to fully remove wholesale. Subsequent patches will deal with relocation.
|
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Corentin Jabot (cor3ntin) ChangesIn Kona, WG21 decided to revert trivial relocation (P2786). Given that the notion of replaceability that was introduced at the same time does not appear to be used by clang 21 users, and is less likely to come back, it is easier to fully remove wholesale. Subsequent patches will deal with relocation. Patch is 49.04 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/172150.diff 18 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
index 06982b8698e0c..66a6f07efd7bb 100644
--- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
@@ -83,7 +83,6 @@ static const llvm::StringSet<> ValueTraits = {
"is_pointer_interconvertible_base_of",
"is_polymorphic",
"is_reference",
- "is_replaceable",
"is_rvalue_reference",
"is_same",
"is_scalar",
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 87d38e7d99e50..0270d3e07bf76 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2044,8 +2044,6 @@ The following type trait primitives are supported by Clang. Those traits marked
is trivially relocatable, as defined by the C++26 standard [meta.unary.prop].
Note that when relocating the caller code should ensure that if the object is polymorphic,
the dynamic type is of the most derived type. Padding bytes should not be copied.
-* ``__builtin_is_replaceable`` (C++): Returns true if an object
- is replaceable, as defined by the C++26 standard [meta.unary.prop].
* ``__is_trivially_equality_comparable`` (Clang): Returns true if comparing two
objects of the provided type is known to be equivalent to comparing their
object representations. Note that types containing padding bytes are never
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f64e29be3205f..1484ead2d9bfd 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -666,7 +666,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
public:
struct CXXRecordDeclRelocationInfo {
unsigned IsRelocatable;
- unsigned IsReplaceable;
};
std::optional<CXXRecordDeclRelocationInfo>
getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index d8d1675f245a1..4a5f0ea73f518 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1952,14 +1952,6 @@ def TriviallyRelocatable : InheritableAttr {
let Documentation = [InternalOnly];
}
-def Replaceable : InheritableAttr {
- let Spellings = [CustomKeyword<"replaceable_if_eligible">];
- let SemaHandler = 0;
- // Omitted from docs, since this is language syntax, not an attribute, as far
- // as users are concerned.
- let Documentation = [InternalOnly];
-}
-
def MinSize : InheritableAttr {
let Spellings = [Clang<"minsize">];
let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9401377002223..bbaa9db2723ed 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1077,14 +1077,15 @@ def ext_ms_abstract_keyword : ExtWarn<
"'abstract' keyword is a Microsoft extension">,
InGroup<MicrosoftAbstract>;
-def ext_relocatable_keyword : ExtWarn<
- "'%select{trivially_relocatable_if_eligible|replaceable_if_eligible}0' "
- "keyword is a C++2c extension">,
- InGroup<CXX26>;
-def warn_relocatable_keyword : Warning<
- "'%select{trivially_relocatable|replaceable}0_if_eligible' "
- "keyword is incompatible with standards before C++2c">,
- DefaultIgnore, InGroup<CXXPre26Compat>;
+def ext_relocatable_keyword
+ : ExtWarn<
+ "'trivially_relocatable_if_eligible' keyword is a C++2c extension">,
+ InGroup<CXX26>;
+def warn_relocatable_keyword
+ : Warning<"'trivially_relocatable_if_eligible' keyword is incompatible "
+ "with standards before C++2c">,
+ DefaultIgnore,
+ InGroup<CXXPre26Compat>;
def err_access_specifier_interface : Error<
"interface types cannot specify '%select{private|protected}0' access">;
@@ -1092,8 +1093,8 @@ def err_access_specifier_interface : Error<
def err_duplicate_class_virt_specifier : Error<
"class already marked '%0'">;
-def err_duplicate_class_relocation_specifier : Error<
- "class already marked '%select{trivially_relocatable_if_eligible|replaceable_if_eligible}0'">;
+def err_duplicate_class_relocation_specifier
+ : Error<"class already marked 'trivially_relocatable_if_eligible'">;
def err_duplicate_virt_specifier : Error<
"class member already marked '%0'">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9147b6a041c70..9a75ab3b1b3c3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1770,7 +1770,6 @@ def err_user_defined_msg_constexpr : Error<
def note_unsatisfied_trait
: Note<"%0 is not %enum_select<TraitName>{"
"%TriviallyRelocatable{trivially relocatable}|"
- "%Replaceable{replaceable}|"
"%TriviallyCopyable{trivially copyable}|"
"%Empty{empty}|"
"%StandardLayout{standard-layout}|"
@@ -1792,8 +1791,6 @@ def note_unsatisfied_trait_reason
"class type}|"
"%NTRBase{has a non-trivially-relocatable base %1}|"
"%NTRField{has a non-trivially-relocatable member %1 of type %2}|"
- "%NonReplaceableBase{has a non-replaceable base %1}|"
- "%NonReplaceableField{has a non-replaceable member %1 of type %2}|"
"%NTCBase{has a non-trivially-copyable base %1}|"
"%NTCField{has a non-trivially-copyable member %1 of type %2}|"
"%NonEmptyMember{has a non-static data member %1 of type %2}|"
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 564d6010181cc..235ffbaa874a6 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -564,7 +564,6 @@ TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX)
TYPE_TRAIT_1(__builtin_is_cpp_trivially_relocatable, IsCppTriviallyRelocatable, KEYCXX)
TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
TYPE_TRAIT_1(__is_bitwise_cloneable, IsBitwiseCloneable, KEYALL)
-TYPE_TRAIT_1(__builtin_is_replaceable, IsReplaceable, KEYCXX)
TYPE_TRAIT_1(__builtin_structured_binding_size, StructuredBindingSize, KEYCXX)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 58eb1c0a7c114..c67fb32af1eef 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2835,7 +2835,6 @@ class Parser : public CodeCompletionHandler {
mutable IdentifierInfo *Ident_GNU_final;
mutable IdentifierInfo *Ident_override;
mutable IdentifierInfo *Ident_trivially_relocatable_if_eligible;
- mutable IdentifierInfo *Ident_replaceable_if_eligible;
/// Representation of a class that has been parsed, including
/// any member function declarations or definitions that need to be
@@ -3129,7 +3128,7 @@ class Parser : public CodeCompletionHandler {
/// isClassCompatibleKeyword - Determine whether the next token is a C++11
/// 'final', a C++26 'trivially_relocatable_if_eligible',
- /// 'replaceable_if_eligible', or Microsoft 'sealed' or 'abstract' contextual
+ /// or Microsoft 'sealed' or 'abstract' contextual
/// keyword.
bool isClassCompatibleKeyword() const;
@@ -3603,12 +3602,8 @@ class Parser : public CodeCompletionHandler {
bool isCXX2CTriviallyRelocatableKeyword() const;
void ParseCXX2CTriviallyRelocatableSpecifier(SourceLocation &TRS);
- bool isCXX2CReplaceableKeyword(Token Tok) const;
- bool isCXX2CReplaceableKeyword() const;
- void ParseCXX2CReplaceableSpecifier(SourceLocation &MRS);
-
/// 'final', a C++26 'trivially_relocatable_if_eligible',
- /// 'replaceable_if_eligible', or Microsoft 'sealed' or 'abstract' contextual
+ /// or Microsoft 'sealed' or 'abstract' contextual
/// keyword.
bool isClassCompatibleKeyword(Token Tok) const;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d14b5dc5ffaa4..1ddfae54b4b4b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4366,7 +4366,6 @@ class Sema final : public SemaBase {
bool IsFinalSpelledSealed,
bool IsAbstract,
SourceLocation TriviallyRelocatable,
- SourceLocation Replaceable,
SourceLocation LBraceLoc);
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
@@ -4375,7 +4374,7 @@ class Sema final : public SemaBase {
SourceRange BraceRange);
ASTContext::CXXRecordDeclRelocationInfo
- CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D);
+ CheckCXX2CRelocatable(const clang::CXXRecordDecl *D);
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
@@ -8733,12 +8732,6 @@ class Sema final : public SemaBase {
bool IsCXXTriviallyRelocatableType(QualType T);
bool IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD);
- //// Determines if a type is replaceable
- /// according to the C++26 rules.
- // FIXME: This is in Sema because it requires
- // overload resolution, can we move to ASTContext?
- bool IsCXXReplaceableType(QualType T);
-
/// Check the operands of ?: under C++ semantics.
///
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index d8ed7e3ff96bd..6b67a2aa99cc7 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2498,40 +2498,13 @@ void Parser::ParseCXX2CTriviallyRelocatableSpecifier(SourceLocation &TRS) {
Diag(Tok.getLocation(), getLangOpts().CPlusPlus26
? diag::warn_relocatable_keyword
- : diag::ext_relocatable_keyword)
- << /*relocatable*/ 0;
+ : diag::ext_relocatable_keyword);
TRS = ConsumeToken();
}
-bool Parser::isCXX2CReplaceableKeyword(Token Tok) const {
- if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))
- return false;
- if (!Ident_replaceable_if_eligible)
- Ident_replaceable_if_eligible =
- &PP.getIdentifierTable().get("replaceable_if_eligible");
- IdentifierInfo *II = Tok.getIdentifierInfo();
- return II == Ident_replaceable_if_eligible;
-}
-
-bool Parser::isCXX2CReplaceableKeyword() const {
- return isCXX2CReplaceableKeyword(Tok);
-}
-
-void Parser::ParseCXX2CReplaceableSpecifier(SourceLocation &MRS) {
- assert(isCXX2CReplaceableKeyword() &&
- "expected a replaceable_if_eligible specifier");
-
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus26
- ? diag::warn_relocatable_keyword
- : diag::ext_relocatable_keyword)
- << /*replaceable*/ 1;
-
- MRS = ConsumeToken();
-}
-
bool Parser::isClassCompatibleKeyword(Token Tok) const {
- if (isCXX2CTriviallyRelocatableKeyword(Tok) || isCXX2CReplaceableKeyword(Tok))
+ if (isCXX2CTriviallyRelocatableKeyword(Tok))
return true;
VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
return Specifier == VirtSpecifiers::VS_Final ||
@@ -3587,7 +3560,6 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
bool IsFinalSpelledSealed = false;
bool IsAbstract = false;
SourceLocation TriviallyRelocatable;
- SourceLocation Replaceable;
// Parse the optional 'final' keyword.
if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
@@ -3599,23 +3571,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
auto Skipped = Tok;
ConsumeToken();
Diag(Skipped, diag::err_duplicate_class_relocation_specifier)
- << /*trivial_relocatable*/ 0 << TriviallyRelocatable;
+ << TriviallyRelocatable;
} else {
ParseCXX2CTriviallyRelocatableSpecifier(TriviallyRelocatable);
}
continue;
}
- if (isCXX2CReplaceableKeyword(Tok)) {
- if (Replaceable.isValid()) {
- auto Skipped = Tok;
- ConsumeToken();
- Diag(Skipped, diag::err_duplicate_class_relocation_specifier)
- << /*replaceable*/ 1 << Replaceable;
- } else {
- ParseCXX2CReplaceableSpecifier(Replaceable);
- }
- continue;
- }
break;
}
if (isCXX11FinalKeyword()) {
@@ -3654,7 +3615,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
Diag(FinalLoc, diag::ext_warn_gnu_final);
}
assert((FinalLoc.isValid() || AbstractLoc.isValid() ||
- TriviallyRelocatable.isValid() || Replaceable.isValid()) &&
+ TriviallyRelocatable.isValid()) &&
"not a class definition");
// Parse any C++11 attributes after 'final' keyword.
@@ -3729,7 +3690,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (TagDecl)
Actions.ActOnStartCXXMemberDeclarations(
getCurScope(), TagDecl, FinalLoc, IsFinalSpelledSealed, IsAbstract,
- TriviallyRelocatable, Replaceable, T.getOpenLocation());
+ TriviallyRelocatable, T.getOpenLocation());
// C++ 11p3: Members of a class defined with the keyword class are private
// by default. Members of a class defined with the keywords struct or union
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 7b425dd3dda43..1f32bf8009ded 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -515,7 +515,6 @@ void Parser::Initialize() {
Ident_abstract = nullptr;
Ident_override = nullptr;
Ident_trivially_relocatable_if_eligible = nullptr;
- Ident_replaceable_if_eligible = nullptr;
Ident_GNU_final = nullptr;
Ident_import = nullptr;
Ident_module = nullptr;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 47bd7295e93f6..9285238e4dfb9 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18794,10 +18794,12 @@ bool Sema::ActOnDuplicateDefinition(Scope *S, Decl *Prev,
return true;
}
-void Sema::ActOnStartCXXMemberDeclarations(
- Scope *S, Decl *TagD, SourceLocation FinalLoc, bool IsFinalSpelledSealed,
- bool IsAbstract, SourceLocation TriviallyRelocatable,
- SourceLocation Replaceable, SourceLocation LBraceLoc) {
+void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
+ SourceLocation FinalLoc,
+ bool IsFinalSpelledSealed,
+ bool IsAbstract,
+ SourceLocation TriviallyRelocatable,
+ SourceLocation LBraceLoc) {
AdjustDeclIfTemplate(TagD);
CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
@@ -18820,9 +18822,6 @@ void Sema::ActOnStartCXXMemberDeclarations(
Record->addAttr(
TriviallyRelocatableAttr::Create(Context, TriviallyRelocatable));
- if (Replaceable.isValid())
- Record->addAttr(ReplaceableAttr::Create(Context, Replaceable));
-
// C++ [class]p2:
// [...] The class-name is also inserted into the scope of the
// class itself; this is known as the injected-class-name. For
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index 38877967af05e..f9d223a67e393 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -211,49 +211,15 @@ static bool IsEligibleForTrivialRelocation(Sema &SemaRef,
return !D->hasDeletedDestructor();
}
-// [C++26][class.prop]
-// A class C is eligible for replacement unless
-static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D) {
-
- for (const CXXBaseSpecifier &B : D->bases()) {
- const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
- if (!BaseDecl)
- continue;
- // it has a base class that is not a replaceable class
- if (!BaseDecl->isDependentType() &&
- !SemaRef.IsCXXReplaceableType(B.getType()))
- return false;
- }
-
- for (const FieldDecl *Field : D->fields()) {
- if (Field->getType()->isDependentType())
- continue;
-
- // it has a non-static data member that is not of a replaceable type,
- if (!SemaRef.IsCXXReplaceableType(Field->getType()))
- return false;
- }
- return !D->hasDeletedDestructor();
-}
-
ASTContext::CXXRecordDeclRelocationInfo
-Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
- ASTContext::CXXRecordDeclRelocationInfo Info{false, false};
+Sema::CheckCXX2CRelocatable(const CXXRecordDecl *D) {
+ ASTContext::CXXRecordDeclRelocationInfo Info{false};
if (!getLangOpts().CPlusPlus || D->isInvalidDecl())
return Info;
assert(D->hasDefinition());
- // This is part of "eligible for replacement", however we defer it
- // to avoid extraneous computations.
- auto HasSuitableSMP = [&] {
- return hasSuitableConstructorForRelocation(*this, D,
- /*AllowUserDefined=*/true) &&
- hasSuitableMoveAssignmentOperatorForRelocation(
- *this, D, /*AllowUserDefined=*/true);
- };
-
auto IsUnion = [&, Is = std::optional<bool>{}]() mutable {
if (!Is.has_value())
Is = D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&
@@ -289,26 +255,6 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
return IsDefaultMovable();
}();
- Info.IsReplaceable = [&] {
- if (D->isDependentType())
- return false;
-
- // A class C is a replaceable class if it is eligible for replacement
- if (!IsEligibleForReplacement(*this, D))
- return false;
-
- // has the replaceable_if_eligible class-property-specifier
- if (D->hasAttr<ReplaceableAttr>())
- return HasSuitableSMP();
-
- // is a union with no user-declared special member functions, or
- if (IsUnion())
- return HasSuitableSMP();
-
- // is default-movable.
- return IsDefaultMovable();
- }();
-
return Info;
}
@@ -316,8 +262,7 @@ bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) {
if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
getASTContext().getRelocationInfoForCXXRecord(&RD))
return Info->IsRelocatable;
- ASTContext::CXXRecordDeclRelocationInfo Info =
- CheckCXX2CRelocatableAndReplaceable(&RD);
+ ASTContext::CXXRecordDeclRelocationInfo Info = CheckCXX2CRelocatable(&RD);
getASTContext().setRelocationInfoForCXXRecord(&RD, Info);
return Info.IsRelocatable;
}
@@ -346,34 +291,6 @@ bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
return false;
}
-static bool IsCXXReplaceableType(Sema &S, const CXXRecordDecl *RD) {
- if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
- S.getASTContext().getRelocationInfoForCXXRecord(RD))
- return Info->IsReplaceable;
- ASTContext::CXXRecordDeclRelocationInfo Info =
- S.CheckCXX2CRelocatableAndReplaceable(RD);
- S.getASTContext().setRelocationInfoForCXXRecord(RD, Info);
- return Info.IsReplaceable;
-}
-
-bool Sema::IsCXXReplaceableType(QualType Type) {
- if (Type.isConstQualified() || Type.isVolatileQualified())
- return false;
-
- if (Type->isVariableArrayType())
- return false;
-
- QualType BaseElementType =
- getASTContext().getBaseElementType(Type.getUnqualifiedType());
- if (BaseElementType->isIncompleteType())
- return false;
- if (BaseElementType->isScalarType())
- return true;
- if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
- return ::IsCXXReplaceableType(*this, RD);
- return false;
-}
-
/// Checks that type T is not a VLA.
///
/// @returns @c true if @p T is VLA and a diagnostic was emitted,
@@ -526,7 +443,6 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsTriviallyRelocatable:
case UTT_IsTriviallyEqualityComparable:
case UTT_IsCppTriviallyRelocatable:
- case UTT_IsReplaceable:
case UTT_CanPassInRegs:
// Per the GCC type traits documentation, T shall be a complete type, cv void,
// or an arra...
[truncated]
|
ojhunt
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadness, but 👍
In Kona, WG21 decided to revert trivial relocation (P2786).
Given that the notion of replaceability that was introduced at the same time does not appear to be used by clang 21 users, and is less likely to come back, it is easier to fully remove wholesale.
Subsequent patches will deal with relocation.