Skip to content

Commit 4065271

Browse files
committed
[clang] Fix PointerAuth semantics of __builtin_is_cpp_trivially_relocatable
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.
1 parent c0c0f60 commit 4065271

File tree

8 files changed

+313
-86
lines changed

8 files changed

+313
-86
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -620,18 +620,61 @@ class ASTContext : public RefCountedBase<ASTContext> {
620620
ParameterIndexTable ParamIndices;
621621

622622
public:
623-
struct CXXRecordDeclRelocationInfo {
624-
unsigned IsRelocatable;
625-
unsigned IsReplaceable;
623+
struct TypeRelocationInfo {
624+
static TypeRelocationInfo invalid() {
625+
TypeRelocationInfo Result;
626+
Result.IsRelocatable = false;
627+
Result.IsReplaceable = false;
628+
return Result;
629+
}
630+
631+
TypeRelocationInfo() {}
632+
TypeRelocationInfo(bool IsRelocatable, bool IsReplaceable,
633+
bool HasAddressDiscriminatedValues)
634+
: IsUnion(false), IsRelocatable(IsRelocatable),
635+
IsReplaceable(IsReplaceable),
636+
HasAddressDiscriminatedValues(HasAddressDiscriminatedValues) {}
637+
638+
void setIsUnion(bool Union) {
639+
IsUnion = Union;
640+
normalizeState();
641+
}
642+
void updateRelocatable(bool Relocatable) { IsRelocatable &= Relocatable; }
643+
void updateReplaceable(bool Replaceable) { IsReplaceable &= Replaceable; }
644+
void
645+
updateContainsAddressDiscriminatedValues(bool AddressDiscriminatedValues) {
646+
HasAddressDiscriminatedValues |= AddressDiscriminatedValues;
647+
normalizeState();
648+
}
649+
void mergeWithSiblingMember(bool IsUnion, const TypeRelocationInfo &Other) {
650+
updateRelocatable(Other.IsRelocatable);
651+
updateReplaceable(Other.IsReplaceable);
652+
normalizeState();
653+
}
654+
bool isRelocatable() const { return IsRelocatable; }
655+
bool isReplaceable() const { return IsReplaceable; }
656+
bool hasAddressDiscriminatedPointerAuth() const {
657+
return HasAddressDiscriminatedValues;
658+
}
659+
660+
private:
661+
void normalizeState() {
662+
if (!IsUnion || !HasAddressDiscriminatedValues)
663+
return;
664+
IsRelocatable = false;
665+
IsReplaceable = false;
666+
}
667+
bool IsUnion = false;
668+
bool IsRelocatable = true;
669+
bool IsReplaceable = true;
670+
bool HasAddressDiscriminatedValues = false;
626671
};
627-
std::optional<CXXRecordDeclRelocationInfo>
672+
std::optional<TypeRelocationInfo>
628673
getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
629-
void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
630-
CXXRecordDeclRelocationInfo);
674+
void setRelocationInfoForCXXRecord(const CXXRecordDecl *, TypeRelocationInfo);
631675

632676
private:
633-
llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
634-
RelocatableClasses;
677+
llvm::DenseMap<const CXXRecordDecl *, TypeRelocationInfo> RelocationInfo;
635678

636679
ImportDecl *FirstLocalImport = nullptr;
637680
ImportDecl *LastLocalImport = nullptr;
@@ -3668,6 +3711,7 @@ OPT_LIST(V)
36683711
/// authentication policy for the specified record.
36693712
const CXXRecordDecl *
36703713
baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
3714+
bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
36713715
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
36723716
StringRef MangledName);
36733717

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4343,8 +4343,10 @@ class Sema final : public SemaBase {
43434343
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
43444344
SourceRange BraceRange);
43454345

4346-
ASTContext::CXXRecordDeclRelocationInfo
4347-
CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D);
4346+
ASTContext::TypeRelocationInfo
4347+
GetCXX2CTypeRelocationInfo(const clang::CXXRecordDecl *D);
4348+
4349+
ASTContext::TypeRelocationInfo GetCXX2CTypeRelocationInfo(QualType T);
43484350

43494351
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
43504352

@@ -8680,7 +8682,6 @@ class Sema final : public SemaBase {
86808682
// FIXME: This is in Sema because it requires
86818683
// overload resolution, can we move to ASTContext?
86828684
bool IsCXXTriviallyRelocatableType(QualType T);
8683-
bool IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD);
86848685

86858686
//// Determines if a type is replaceable
86868687
/// according to the C++26 rules.

clang/lib/AST/ASTContext.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,22 +1687,22 @@ void ASTContext::getOverriddenMethods(
16871687
Overridden.append(OverDecls.begin(), OverDecls.end());
16881688
}
16891689

1690-
std::optional<ASTContext::CXXRecordDeclRelocationInfo>
1690+
std::optional<ASTContext::TypeRelocationInfo>
16911691
ASTContext::getRelocationInfoForCXXRecord(const CXXRecordDecl *RD) const {
16921692
assert(RD);
16931693
CXXRecordDecl *D = RD->getDefinition();
1694-
auto it = RelocatableClasses.find(D);
1695-
if (it != RelocatableClasses.end())
1694+
auto it = RelocationInfo.find(D);
1695+
if (it != RelocationInfo.end())
16961696
return it->getSecond();
16971697
return std::nullopt;
16981698
}
16991699

1700-
void ASTContext::setRelocationInfoForCXXRecord(
1701-
const CXXRecordDecl *RD, CXXRecordDeclRelocationInfo Info) {
1700+
void ASTContext::setRelocationInfoForCXXRecord(const CXXRecordDecl *RD,
1701+
TypeRelocationInfo Info) {
17021702
assert(RD);
17031703
CXXRecordDecl *D = RD->getDefinition();
1704-
assert(RelocatableClasses.find(D) == RelocatableClasses.end());
1705-
RelocatableClasses.insert({D, Info});
1704+
assert(RelocationInfo.find(D) == RelocationInfo.end());
1705+
RelocationInfo.insert({D, Info});
17061706
}
17071707

17081708
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
@@ -15121,6 +15121,21 @@ ASTContext::baseForVTableAuthentication(const CXXRecordDecl *ThisClass) {
1512115121
return PrimaryBase;
1512215122
}
1512315123

15124+
bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
15125+
const CXXRecordDecl *Class) {
15126+
assert(Class->isPolymorphic());
15127+
const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
15128+
using AuthAttr = VTablePointerAuthenticationAttr;
15129+
const auto *ExplicitAuth = BaseType->getAttr<AuthAttr>();
15130+
if (!ExplicitAuth)
15131+
return LangOpts.PointerAuthVTPtrAddressDiscrimination;
15132+
AuthAttr::AddressDiscriminationMode AddressDiscrimination =
15133+
ExplicitAuth->getAddressDiscrimination();
15134+
if (AddressDiscrimination == AuthAttr::DefaultAddressDiscrimination)
15135+
return LangOpts.PointerAuthVTPtrAddressDiscrimination;
15136+
return AddressDiscrimination == AuthAttr::AddressDiscrimination;
15137+
}
15138+
1512415139
bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
1512515140
StringRef MangledName) {
1512615141
auto *Method = cast<CXXMethodDecl>(VirtualMethodDecl.getDecl());

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10615,7 +10615,7 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
1061510615
}
1061610616
}
1061710617

10618-
if (IsCXXTriviallyRelocatableType(RD))
10618+
if (GetCXX2CTypeRelocationInfo(&RD).isRelocatable())
1061910619
return;
1062010620

1062110621
// Ill-formed if the copy and move constructors are deleted.

0 commit comments

Comments
 (0)