Skip to content

Commit 3190a52

Browse files
committed
Add comments and more tests
1 parent f476803 commit 3190a52

File tree

4 files changed

+76
-16
lines changed

4 files changed

+76
-16
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,11 +628,25 @@ 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+
// A simple helper function to short circuit pointer auth checks.
641+
bool isPointerAuthenticationAvailable() const {
642+
return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics ||
643+
LangOpts.PointerAuthVTPtrAddressDiscrimination;
644+
}
645+
634646
llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
635647
RelocatableClasses;
648+
649+
// FIXME: store in RecordDeclBitfields in future?
636650
llvm::DenseMap<const RecordDecl *, bool>
637651
RecordContainsAddressDiscriminatedPointerAuth;
638652

@@ -3671,7 +3685,13 @@ OPT_LIST(V)
36713685
/// authentication policy for the specified record.
36723686
const CXXRecordDecl *
36733687
baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
3688+
3689+
/// If this class is polymorphic, returns true if any of this class's
3690+
/// vtable pointers have an address discriminated pointer authentication
3691+
/// schema.
3692+
/// This does not check fields of the class or base classes.
36743693
bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
3694+
36753695
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
36763696
StringRef MangledName);
36773697

clang/lib/AST/ASTContext.cpp

Lines changed: 8 additions & 6 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();
@@ -1716,13 +1716,14 @@ bool ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
17161716
if (!RD)
17171717
return false;
17181718

1719+
if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
1720+
Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
1721+
return Existing->second;
1722+
17191723
auto SaveReturn = [this, RD](bool Result) {
17201724
RecordContainsAddressDiscriminatedPointerAuth.insert({RD, Result});
17211725
return Result;
17221726
};
1723-
if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
1724-
Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
1725-
return Existing->second;
17261727
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
17271728
if (CXXRD->isPolymorphic() &&
17281729
hasAddressDiscriminatedVTableAuthentication(CXXRD))
@@ -15157,10 +15158,11 @@ ASTContext::baseForVTableAuthentication(const CXXRecordDecl *ThisClass) {
1515715158

1515815159
bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
1515915160
const CXXRecordDecl *Class) {
15160-
assert(Class->isPolymorphic());
15161+
if (!isPointerAuthenticationAvailable() || !Class->isPolymorphic())
15162+
return false;
1516115163
const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
1516215164
using AuthAttr = VTablePointerAuthenticationAttr;
15163-
const auto *ExplicitAuth = BaseType->getAttr<AuthAttr>();
15165+
const AuthAttr *ExplicitAuth = BaseType->getAttr<AuthAttr>();
1516415166
if (!ExplicitAuth)
1516515167
return LangOpts.PointerAuthVTPtrAddressDiscrimination;
1516615168
AuthAttr::AddressDiscriminationMode AddressDiscrimination =

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 10 additions & 6 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;
202-
if (IsUnion &&
203-
SemaRef.Context.containsAddressDiscriminatedPointerAuth(FieldType))
201+
202+
// A union contains values with address discriminated pointer auth
203+
// cannot be relocated.
204+
if (IsUnion && SemaRef.Context.containsAddressDiscriminatedPointerAuth(
205+
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)