[clang] [clang] Fix PointerAuth semantics of cpp_trivially_relocatable (PR #143796)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 11 15:18:05 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Oliver Hunt (ojhunt)
<details>
<summary>Changes</summary>
This reworks the way we compute relocatability and replaceability of types. We do this by having a single interface the provides a full `TypeRelocationInfo` for a QualType. This simplifies the reasoning for all cases, and reduces duplication of code.
We still limit our caching of results to CXXRecordDecls but i think it might be worth caching on canonical types in future, but for now I didn't want to change the caching semantics any further.
TypeRelocationInfo no longer permits raw field access as we can then ensure we maintain correct state over pointer auth and similar.
As a basic optimization we gate the additional required work on the existence pointer auth options.
---
Patch is 23.04 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143796.diff
8 Files Affected:
- (modified) clang/include/clang/AST/ASTContext.h (+52-8)
- (modified) clang/include/clang/Sema/Sema.h (+4-3)
- (modified) clang/lib/AST/ASTContext.cpp (+22-7)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+1-1)
- (modified) clang/lib/Sema/SemaTypeTraits.cpp (+126-62)
- (modified) clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp (+1)
- (modified) clang/test/SemaCXX/ptrauth-triviality.cpp (+5-5)
- (added) clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp (+102)
``````````diff
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 8d24d393eab09..4526189a83348 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -620,18 +620,61 @@ class ASTContext : public RefCountedBase<ASTContext> {
ParameterIndexTable ParamIndices;
public:
- struct CXXRecordDeclRelocationInfo {
- unsigned IsRelocatable;
- unsigned IsReplaceable;
+ struct TypeRelocationInfo {
+ static TypeRelocationInfo invalid() {
+ TypeRelocationInfo Result;
+ Result.IsRelocatable = false;
+ Result.IsReplaceable = false;
+ return Result;
+ }
+
+ TypeRelocationInfo() {}
+ TypeRelocationInfo(bool IsRelocatable, bool IsReplaceable,
+ bool HasAddressDiscriminatedValues)
+ : IsUnion(false), IsRelocatable(IsRelocatable),
+ IsReplaceable(IsReplaceable),
+ HasAddressDiscriminatedValues(HasAddressDiscriminatedValues) {}
+
+ void setIsUnion(bool Union) {
+ IsUnion = Union;
+ normalizeState();
+ }
+ void updateRelocatable(bool Relocatable) { IsRelocatable &= Relocatable; }
+ void updateReplaceable(bool Replaceable) { IsReplaceable &= Replaceable; }
+ void
+ updateContainsAddressDiscriminatedValues(bool AddressDiscriminatedValues) {
+ HasAddressDiscriminatedValues |= AddressDiscriminatedValues;
+ normalizeState();
+ }
+ void mergeWithSiblingMember(bool IsUnion, const TypeRelocationInfo &Other) {
+ updateRelocatable(Other.IsRelocatable);
+ updateReplaceable(Other.IsReplaceable);
+ normalizeState();
+ }
+ bool isRelocatable() const { return IsRelocatable; }
+ bool isReplaceable() const { return IsReplaceable; }
+ bool hasAddressDiscriminatedPointerAuth() const {
+ return HasAddressDiscriminatedValues;
+ }
+
+ private:
+ void normalizeState() {
+ if (!IsUnion || !HasAddressDiscriminatedValues)
+ return;
+ IsRelocatable = false;
+ IsReplaceable = false;
+ }
+ bool IsUnion = false;
+ bool IsRelocatable = true;
+ bool IsReplaceable = true;
+ bool HasAddressDiscriminatedValues = false;
};
- std::optional<CXXRecordDeclRelocationInfo>
+ std::optional<TypeRelocationInfo>
getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
- void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
- CXXRecordDeclRelocationInfo);
+ void setRelocationInfoForCXXRecord(const CXXRecordDecl *, TypeRelocationInfo);
private:
- llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
- RelocatableClasses;
+ llvm::DenseMap<const CXXRecordDecl *, TypeRelocationInfo> RelocationInfo;
ImportDecl *FirstLocalImport = nullptr;
ImportDecl *LastLocalImport = nullptr;
@@ -3668,6 +3711,7 @@ OPT_LIST(V)
/// authentication policy for the specified record.
const CXXRecordDecl *
baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
+ bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
StringRef MangledName);
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0dad07e55a820..5e405c604598a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4343,8 +4343,10 @@ class Sema final : public SemaBase {
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
SourceRange BraceRange);
- ASTContext::CXXRecordDeclRelocationInfo
- CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D);
+ ASTContext::TypeRelocationInfo
+ GetCXX2CTypeRelocationInfo(const clang::CXXRecordDecl *D);
+
+ ASTContext::TypeRelocationInfo GetCXX2CTypeRelocationInfo(QualType T);
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
@@ -8680,7 +8682,6 @@ class Sema final : public SemaBase {
// FIXME: This is in Sema because it requires
// overload resolution, can we move to ASTContext?
bool IsCXXTriviallyRelocatableType(QualType T);
- bool IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD);
//// Determines if a type is replaceable
/// according to the C++26 rules.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b51f7622288df..b4f1133e6adcd 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1687,22 +1687,22 @@ void ASTContext::getOverriddenMethods(
Overridden.append(OverDecls.begin(), OverDecls.end());
}
-std::optional<ASTContext::CXXRecordDeclRelocationInfo>
+std::optional<ASTContext::TypeRelocationInfo>
ASTContext::getRelocationInfoForCXXRecord(const CXXRecordDecl *RD) const {
assert(RD);
CXXRecordDecl *D = RD->getDefinition();
- auto it = RelocatableClasses.find(D);
- if (it != RelocatableClasses.end())
+ auto it = RelocationInfo.find(D);
+ if (it != RelocationInfo.end())
return it->getSecond();
return std::nullopt;
}
-void ASTContext::setRelocationInfoForCXXRecord(
- const CXXRecordDecl *RD, CXXRecordDeclRelocationInfo Info) {
+void ASTContext::setRelocationInfoForCXXRecord(const CXXRecordDecl *RD,
+ TypeRelocationInfo Info) {
assert(RD);
CXXRecordDecl *D = RD->getDefinition();
- assert(RelocatableClasses.find(D) == RelocatableClasses.end());
- RelocatableClasses.insert({D, Info});
+ assert(RelocationInfo.find(D) == RelocationInfo.end());
+ RelocationInfo.insert({D, Info});
}
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
@@ -15121,6 +15121,21 @@ ASTContext::baseForVTableAuthentication(const CXXRecordDecl *ThisClass) {
return PrimaryBase;
}
+bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
+ const CXXRecordDecl *Class) {
+ assert(Class->isPolymorphic());
+ const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
+ using AuthAttr = VTablePointerAuthenticationAttr;
+ const auto *ExplicitAuth = BaseType->getAttr<AuthAttr>();
+ if (!ExplicitAuth)
+ return LangOpts.PointerAuthVTPtrAddressDiscrimination;
+ AuthAttr::AddressDiscriminationMode AddressDiscrimination =
+ ExplicitAuth->getAddressDiscrimination();
+ if (AddressDiscrimination == AuthAttr::DefaultAddressDiscrimination)
+ return LangOpts.PointerAuthVTPtrAddressDiscrimination;
+ return AddressDiscrimination == AuthAttr::AddressDiscrimination;
+}
+
bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
StringRef MangledName) {
auto *Method = cast<CXXMethodDecl>(VirtualMethodDecl.getDecl());
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 39d4d49a0fe79..8e79e975dc270 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -10615,7 +10615,7 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
}
}
- if (IsCXXTriviallyRelocatableType(RD))
+ if (GetCXX2CTypeRelocationInfo(&RD).isRelocatable())
return;
// Ill-formed if the copy and move constructors are deleted.
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index 1738ab4466001..e2f1322df42a1 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -226,12 +226,13 @@ static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D) {
return !D->hasDeletedDestructor();
}
-ASTContext::CXXRecordDeclRelocationInfo
-Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
- ASTContext::CXXRecordDeclRelocationInfo Info{false, false};
+ASTContext::TypeRelocationInfo
+Sema::GetCXX2CTypeRelocationInfo(const CXXRecordDecl *D) {
+ if (auto ExistingInfo = Context.getRelocationInfoForCXXRecord(D))
+ return *ExistingInfo;
if (!getLangOpts().CPlusPlus || D->isInvalidDecl())
- return Info;
+ return ASTContext::TypeRelocationInfo::invalid();
assert(D->hasDefinition());
@@ -244,12 +245,11 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
*this, D, /*AllowUserDefined=*/true);
};
- auto IsUnion = [&, Is = std::optional<bool>{}]() mutable {
+ auto IsTrivialUnion = [&, Is = std::optional<bool>{}]() mutable {
if (!Is.has_value())
Is = D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&
!D->hasUserDeclaredCopyAssignment() &&
- !D->hasUserDeclaredMoveOperation() &&
- !D->hasUserDeclaredDestructor();
+ !D->hasUserDeclaredMoveOperation() && !D->hasUserDeclaredDestructor();
return *Is;
};
@@ -259,7 +259,9 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
return *Is;
};
- Info.IsRelocatable = [&] {
+ ASTContext::TypeRelocationInfo Info;
+
+ Info.updateRelocatable([&] {
if (D->isDependentType())
return false;
@@ -272,14 +274,14 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
return true;
// is a union with no user-declared special member functions, or
- if (IsUnion())
+ if (IsTrivialUnion())
return true;
// is default-movable.
return IsDefaultMovable();
- }();
+ }());
- Info.IsReplaceable = [&] {
+ Info.updateReplaceable([&] {
if (D->isDependentType())
return false;
@@ -292,77 +294,133 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
return HasSuitableSMP();
// is a union with no user-declared special member functions, or
- if (IsUnion())
+ if (IsTrivialUnion())
return HasSuitableSMP();
// is default-movable.
return IsDefaultMovable();
- }();
-
+ }());
+
+ Info.setIsUnion(D->isUnion());
+
+ bool PtrauthMatters = LangOpts.PointerAuthIntrinsics ||
+ LangOpts.PointerAuthVTPtrAddressDiscrimination;
+ if (PtrauthMatters) {
+ auto IsBottomRelocationInfo =
+ [](const ASTContext::TypeRelocationInfo &Info) {
+ return !Info.isReplaceable() && !Info.isRelocatable() &&
+ Info.hasAddressDiscriminatedPointerAuth();
+ };
+
+ if (D->isPolymorphic())
+ Info.updateContainsAddressDiscriminatedValues(
+ Context.hasAddressDiscriminatedVTableAuthentication(D));
+ for (auto Base : D->bases()) {
+ if (IsBottomRelocationInfo(Info))
+ break;
+ bool BaseHasPtrauth = GetCXX2CTypeRelocationInfo(Base.getType())
+ .hasAddressDiscriminatedPointerAuth();
+ Info.updateContainsAddressDiscriminatedValues(BaseHasPtrauth);
+ }
+ for (auto *FieldDecl : D->fields()) {
+ if (IsBottomRelocationInfo(Info))
+ break;
+ bool FieldHasPtrauth = GetCXX2CTypeRelocationInfo(FieldDecl->getType())
+ .hasAddressDiscriminatedPointerAuth();
+ Info.updateContainsAddressDiscriminatedValues(FieldHasPtrauth);
+ }
+ }
+ Context.setRelocationInfoForCXXRecord(D, Info);
return Info;
}
-bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) {
- if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
- getASTContext().getRelocationInfoForCXXRecord(&RD))
- return Info->IsRelocatable;
- ASTContext::CXXRecordDeclRelocationInfo Info =
- CheckCXX2CRelocatableAndReplaceable(&RD);
- getASTContext().setRelocationInfoForCXXRecord(&RD, Info);
- return Info.IsRelocatable;
-}
+ASTContext::TypeRelocationInfo Sema::GetCXX2CTypeRelocationInfo(QualType T) {
+ T = T.getCanonicalType();
+ enum class DirectRelocationInformation { Yes, No, Unknown };
+ DirectRelocationInformation Relocatable =
+ DirectRelocationInformation::Unknown;
+ DirectRelocationInformation Replaceable =
+ DirectRelocationInformation::Unknown;
+ DirectRelocationInformation ContainsAddressDiscriminatedValues =
+ DirectRelocationInformation::Unknown;
+
+ auto UpdateRelocatable = [&](DirectRelocationInformation DRI) {
+ if (Relocatable == DirectRelocationInformation::Unknown ||
+ Relocatable == DirectRelocationInformation::Yes)
+ Relocatable = DRI;
+ };
+ auto UpdateReplaceable = [&](DirectRelocationInformation DRI) {
+ if (Replaceable == DirectRelocationInformation::Unknown ||
+ Replaceable == DirectRelocationInformation::Yes)
+ Replaceable = DRI;
+ };
+ auto UpdateAddressDiscrimination = [&](DirectRelocationInformation DRI) {
+ if (ContainsAddressDiscriminatedValues ==
+ DirectRelocationInformation::Unknown ||
+ ContainsAddressDiscriminatedValues == DirectRelocationInformation::No)
+ ContainsAddressDiscriminatedValues = DRI;
+ };
-bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
+ if (T->isVariableArrayType()) {
+ UpdateRelocatable(DirectRelocationInformation::No);
+ UpdateReplaceable(DirectRelocationInformation::No);
+ }
- QualType BaseElementType = getASTContext().getBaseElementType(Type);
+ if (T.isConstQualified() || T.isVolatileQualified())
+ UpdateReplaceable(DirectRelocationInformation::No);
- if (Type->isVariableArrayType())
- return false;
+ if (T.hasAddressDiscriminatedPointerAuth())
+ UpdateAddressDiscrimination(DirectRelocationInformation::Yes);
+
+ QualType BaseElementType =
+ SemaRef.getASTContext().getBaseElementType(T.getUnqualifiedType());
+
+ if (BaseElementType->isIncompleteType()) {
+ Relocatable = DirectRelocationInformation::No;
+ Replaceable = DirectRelocationInformation::No;
+ }
if (BaseElementType.hasNonTrivialObjCLifetime())
- return false;
+ UpdateRelocatable(DirectRelocationInformation::No);
- if (BaseElementType.hasAddressDiscriminatedPointerAuth())
- return false;
+ if (BaseElementType->isScalarType()) {
+ UpdateRelocatable(DirectRelocationInformation::Yes);
+ UpdateReplaceable(DirectRelocationInformation::Yes);
+ UpdateAddressDiscrimination(DirectRelocationInformation::No);
+ }
- if (BaseElementType->isIncompleteType())
- return false;
+ if (BaseElementType->isVectorType())
+ UpdateRelocatable(DirectRelocationInformation::Yes);
- if (BaseElementType->isScalarType() || BaseElementType->isVectorType())
- return true;
+ auto CreateInfo = [=]() -> ASTContext::TypeRelocationInfo {
+ ASTContext::TypeRelocationInfo Result;
+ return {Relocatable == DirectRelocationInformation::Yes,
+ Replaceable == DirectRelocationInformation::Yes,
+ ContainsAddressDiscriminatedValues ==
+ DirectRelocationInformation::Yes};
+ };
- if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
- return IsCXXTriviallyRelocatableType(*RD);
+ if (BaseElementType->isIncompleteType())
+ return CreateInfo();
- return false;
+ const CXXRecordDecl *RD = BaseElementType->getAsCXXRecordDecl();
+ if (!RD)
+ return CreateInfo();
+
+ ASTContext::TypeRelocationInfo Info = GetCXX2CTypeRelocationInfo(RD);
+ Info.updateRelocatable(Relocatable != DirectRelocationInformation::No);
+ Info.updateReplaceable(Replaceable != DirectRelocationInformation::No);
+ Info.updateContainsAddressDiscriminatedValues(
+ ContainsAddressDiscriminatedValues == DirectRelocationInformation::Yes);
+ return Info;
}
-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::IsCXXTriviallyRelocatableType(QualType Type) {
+ return GetCXX2CTypeRelocationInfo(Type).isRelocatable();
}
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;
+ return GetCXX2CTypeRelocationInfo(Type).isReplaceable();
}
/// Checks that type T is not a VLA.
@@ -674,8 +732,14 @@ static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T) {
return false;
if (const auto *RD = BaseElementType->getAsCXXRecordDecl();
- RD && !RD->isPolymorphic() && SemaRef.IsCXXTriviallyRelocatableType(*RD))
- return true;
+ RD && !RD->isPolymorphic()) {
+ ASTContext::TypeRelocationInfo Info =
+ SemaRef.GetCXX2CTypeRelocationInfo(RD);
+ if (Info.hasAddressDiscriminatedPointerAuth())
+ return false;
+ if (Info.isRelocatable())
+ return true;
+ }
if (const auto *RD = BaseElementType->getAsRecordDecl())
return RD->canPassInRegisters();
diff --git a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp
index 9d43994ee7661..7152a5937d9b7 100644
--- a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp
+++ b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++2c -verify %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-intrinsics -fptrauth-calls -std=c++2c -verify %s
class Trivial {};
static_assert(__builtin_is_cpp_trivially_relocatable(Trivial));
diff --git a/clang/test/SemaCXX/ptrauth-triviality.cpp b/clang/test/SemaCXX/ptrauth-triviality.cpp
index 60d1b57230f18..6f3650f7ac2e3 100644
--- a/clang/test/SemaCXX/ptrauth-triviality.cpp
+++ b/clang/test/SemaCXX/ptrauth-triviality.cpp
@@ -26,7 +26,7 @@ static_assert(!__is_trivially_assignable(S1, const S1&));
static_assert(__is_trivially_destructible(S1));
static_assert(!__is_trivially_copyable(S1));
static_assert(!__is_trivially_relocatable(S1)); // expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(S1));
+static_assert(__builtin_is_cpp_trivially_relocatable(S1));
static_assert(!__is_trivially_equality_comparable(S1));
static_assert(__is_trivially_constructible(Holder<S1>));
@@ -35,7 +35,7 @@ static_assert(!__is_trivially_assignable(Holder<S1>, const Holder<S1>&));
static_assert(__is_trivially_destructible(Holder<S1>));
static_assert(!__is_trivially_copyable(Holder<S1>));
static_assert(!__is_trivially_relocatable(Holder<S1>)); // expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(Holder<S1>));
+static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S1>));
static_assert(!__is_trivially_equality_comparable(Holder<S1>));
struct S2 {
@@ -83,7 +83,7 @@ static_assert(!__is_trivially_constructible(Holder<S3>, const Holder<S3>&));
static_assert(!__is_trivially_assignable(Holder<S3>, const Holder<S3>&));
static_assert(__is_trivially_destructible(Holder<S3>));
static_assert(!__is_trivially_copyable(Holder<S3>));
-static_assert(__is_trivially_relocatable(Holder<S3>)); // expected-warning{{deprecated}}
+static_assert(!__is_trivially_relocatable(Holder<S3>)); // expected-warning{{deprecated}}
static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S3>));
static_assert(!__is_trivially_equality_comparable(Holder<S3>));
@@ -148,7 +148,7 @@ static_assert(!__is_trivially_assignable(S6, const S6&));
static_assert(__is_trivially_destructible(S6));
static_assert(!__is_trivially_copyable(S6));
static_assert(!__is_trivially_relocatable(S6)); // expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(S6));
+static_assert(__builtin_is_cpp_trivially_relocatable(S6));
static_assert(!__is_trivially_equality_comparable(S6));
static_assert(__is_trivially_constructible(Holder<S6>));
@@ -157,7 +157,7 @@ static_assert(!__is_trivially_assignable(Holder<S6>, const Holder<S6>&));
static_assert(__is_trivially_destructible(Holder<S6>));
static_assert(!__is_trivially_copyable(Holder<S6>));
static_assert(!__is_trivially_relocatable(Holder<S6>)); // expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(Holder<S6>));
+static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S6>));
static_assert(!__is_trivially_equality_comparable(Holder<S6>));
struct S7 {
diff --git a/clang/test/SemaCXX/trivi...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/143796
More information about the cfe-commits
mailing list