Skip to content

Commit 286c39e

Browse files
committed
Add comments and more tests
1 parent f476803 commit 286c39e

File tree

4 files changed

+69
-12
lines changed

4 files changed

+69
-12
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,21 @@ class ASTContext : public RefCountedBase<ASTContext> {
628628
getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
629629
void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
630630
CXXRecordDeclRelocationInfo);
631+
632+
/// Examines a given type, and returns whether the T itself
633+
/// is address discriminated, or any transitively embedded types
634+
/// contain data that is address discriminated. This includes
635+
/// implicitly authenticated values like vtable pointers, as well as
636+
/// explicitly qualified fields.
631637
bool containsAddressDiscriminatedPointerAuth(QualType T);
632638

633639
private:
640+
641+
// A simple helper function to short circuit pointer auth checks.
642+
bool isPointerAuthenticationAvailable() const {
643+
return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics || LangOpts.PointerAuthVTPtrAddressDiscrimination;
644+
}
645+
634646
llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
635647
RelocatableClasses;
636648
llvm::DenseMap<const RecordDecl *, bool>
@@ -3671,7 +3683,13 @@ OPT_LIST(V)
36713683
/// authentication policy for the specified record.
36723684
const CXXRecordDecl *
36733685
baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
3686+
3687+
/// If this class is polymorphic, returns true if any of this class's
3688+
/// vtable pointers have an address discriminated pointer authentication
3689+
/// schema.
3690+
/// This does not check fields of the class or base classes.
36743691
bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
3692+
36753693
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
36763694
StringRef MangledName);
36773695

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,7 @@ void ASTContext::setRelocationInfoForCXXRecord(
17061706
}
17071707

17081708
bool ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
1709-
if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthIntrinsics)
1709+
if (!isPointerAuthenticationAvailable())
17101710
return false;
17111711

17121712
T = T.getCanonicalType();
@@ -15157,10 +15157,11 @@ ASTContext::baseForVTableAuthentication(const CXXRecordDecl *ThisClass) {
1515715157

1515815158
bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
1515915159
const CXXRecordDecl *Class) {
15160-
assert(Class->isPolymorphic());
15160+
if (!isPointerAuthenticationAvailable() || !Class->isPolymorphic())
15161+
return false;
1516115162
const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
1516215163
using AuthAttr = VTablePointerAuthenticationAttr;
15163-
const auto *ExplicitAuth = BaseType->getAttr<AuthAttr>();
15164+
const AuthAttr *ExplicitAuth = BaseType->getAttr<AuthAttr>();
1516415165
if (!ExplicitAuth)
1516515166
return LangOpts.PointerAuthVTPtrAddressDiscrimination;
1516615167
AuthAttr::AddressDiscriminationMode AddressDiscrimination =

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,19 @@ static bool IsEligibleForTrivialRelocation(Sema &SemaRef,
190190

191191
bool IsUnion = D->isUnion();
192192
for (const FieldDecl *Field : D->fields()) {
193-
QualType FieldType = Field->getType();
194-
if (FieldType->isDependentType())
193+
if (Field->getType()->isDependentType())
195194
continue;
196-
if (FieldType->isReferenceType())
195+
if (Field->getType()->isReferenceType())
197196
continue;
198197
// ... has a non-static data member of an object type that is not
199198
// of a trivially relocatable type
200199
if (!SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))
201200
return false;
201+
202+
// A union contains values with address discriminated pointer auth
203+
// cannot be relocated.
202204
if (IsUnion &&
203-
SemaRef.Context.containsAddressDiscriminatedPointerAuth(FieldType))
205+
SemaRef.Context.containsAddressDiscriminatedPointerAuth(Field->getType()))
204206
return false;
205207
}
206208
return !D->hasDeletedDestructor();
@@ -318,7 +320,6 @@ bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) {
318320
}
319321

320322
bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
321-
322323
QualType BaseElementType = getASTContext().getBaseElementType(Type);
323324

324325
if (Type->isVariableArrayType())
@@ -672,6 +673,9 @@ static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T) {
672673
if (!BaseElementType->isObjectType())
673674
return false;
674675

676+
// The deprecated __builtin_is_trivially_relocatable does not have
677+
// an equivalent to __builtin_trivially_relocate, so there is no
678+
// safe way to use it if there are any address discriminated values.
675679
if (SemaRef.getASTContext().containsAddressDiscriminatedPointerAuth(T))
676680
return false;
677681

clang/test/SemaCXX/ptrauth-triviality.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++20 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s
2-
// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++20 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s
1+
// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++26 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s
2+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++26 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s
33

44
#define AQ __ptrauth(1,1,50)
55
#define IQ __ptrauth(1,0,50)
@@ -99,7 +99,6 @@ static_assert(!__is_trivially_assignable(S4, const S4&));
9999
static_assert(__is_trivially_destructible(S4));
100100
static_assert(!__is_trivially_copyable(S4));
101101
static_assert(!__is_trivially_relocatable(S4)); // expected-warning{{deprecated}}
102-
//FIXME
103102
static_assert(__builtin_is_cpp_trivially_relocatable(S4));
104103
static_assert(!__is_trivially_equality_comparable(S4));
105104

@@ -124,7 +123,6 @@ static_assert(!__is_trivially_assignable(S5, const S5&));
124123
static_assert(__is_trivially_destructible(S5));
125124
static_assert(!__is_trivially_copyable(S5));
126125
static_assert(!__is_trivially_relocatable(S5)); // expected-warning{{deprecated}}
127-
//FIXME
128126
static_assert(__builtin_is_cpp_trivially_relocatable(S5));
129127
static_assert(!__is_trivially_equality_comparable(S5));
130128

@@ -182,3 +180,39 @@ static_assert(__is_trivially_copyable(Holder<S7>));
182180
static_assert(__is_trivially_relocatable(Holder<S7>)); // expected-warning{{deprecated}}
183181
static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S7>));
184182
static_assert(__is_trivially_equality_comparable(Holder<S7>));
183+
184+
template <class... Bases> struct MultipleInheriter : Bases... {
185+
};
186+
187+
template <class T> static const bool test_is_trivially_relocatable_v = __builtin_is_cpp_trivially_relocatable(T);
188+
template <class... Types> static const bool multiple_inheritance_is_relocatable = test_is_trivially_relocatable_v<MultipleInheriter<Types...>>;
189+
template <class... Types> static const bool inheritance_relocatability_matches_bases_v =
190+
(test_is_trivially_relocatable_v<Types> && ...) == multiple_inheritance_is_relocatable<Types...>;
191+
192+
static_assert(multiple_inheritance_is_relocatable<S4, S5> == multiple_inheritance_is_relocatable<S5, S4>);
193+
static_assert(inheritance_relocatability_matches_bases_v<S4, S5>);
194+
static_assert(inheritance_relocatability_matches_bases_v<S5, S4>);
195+
196+
struct AA AddressDiscriminatedPolymorphicBase trivially_relocatable_if_eligible {
197+
virtual void foo();
198+
};
199+
200+
struct IA NoAddressDiscriminatedPolymorphicBase trivially_relocatable_if_eligible {
201+
virtual void bar();
202+
};
203+
204+
template <class T> struct UnionWrapper trivially_relocatable_if_eligible {
205+
union U {
206+
T field1;
207+
} u;
208+
};
209+
210+
static_assert(test_is_trivially_relocatable_v<AddressDiscriminatedPolymorphicBase>);
211+
static_assert(test_is_trivially_relocatable_v<NoAddressDiscriminatedPolymorphicBase>);
212+
static_assert(inheritance_relocatability_matches_bases_v<AddressDiscriminatedPolymorphicBase, NoAddressDiscriminatedPolymorphicBase>);
213+
static_assert(inheritance_relocatability_matches_bases_v<NoAddressDiscriminatedPolymorphicBase, AddressDiscriminatedPolymorphicBase>);
214+
215+
static_assert(!test_is_trivially_relocatable_v<UnionWrapper<AddressDiscriminatedPolymorphicBase>>);
216+
static_assert(test_is_trivially_relocatable_v<UnionWrapper<NoAddressDiscriminatedPolymorphicBase>>);
217+
static_assert(!test_is_trivially_relocatable_v<UnionWrapper<MultipleInheriter<NoAddressDiscriminatedPolymorphicBase, AddressDiscriminatedPolymorphicBase>>>);
218+
static_assert(!test_is_trivially_relocatable_v<UnionWrapper<MultipleInheriter<AddressDiscriminatedPolymorphicBase, NoAddressDiscriminatedPolymorphicBase>>>);

0 commit comments

Comments
 (0)