[clang] [PAC] Add support for __ptrauth type qualifier (PR #100830)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 1 19:07:45 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: Akira Hatanaka (ahatanak)
<details>
<summary>Changes</summary>
The qualifier allows programmer to directly control how pointers are signed when they are stored in a particular variable.
The qualifier takes three arguments: the signing key, a flag specifying whether address discrimination should be used, and a non-negative integer that is used for additional discrimination.
```
typedef void (*my_callback)(const void*);
my_callback __ptrauth(ptrauth_key_process_dependent_code, 1, 0xe27a) callback;
```
Co-Authored-By: John McCall rjmccall@<!-- -->apple.com
---
Patch is 149.93 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/100830.diff
45 Files Affected:
- (modified) clang/docs/PointerAuthentication.rst (+46)
- (modified) clang/include/clang/AST/Type.h (+17-4)
- (modified) clang/include/clang/Basic/Attr.td (+8)
- (modified) clang/include/clang/Basic/AttrDocs.td (+28)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+44-2)
- (modified) clang/include/clang/Basic/Features.def (+1)
- (modified) clang/include/clang/Basic/TokenKinds.def (+1)
- (modified) clang/include/clang/Parse/Parser.h (+2)
- (modified) clang/include/clang/Sema/Sema.h (+11)
- (modified) clang/lib/AST/ASTContext.cpp (+1)
- (modified) clang/lib/AST/DeclCXX.cpp (+27)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+20)
- (modified) clang/lib/AST/TypePrinter.cpp (+40)
- (modified) clang/lib/CodeGen/CGClass.cpp (+3)
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+17-2)
- (modified) clang/lib/CodeGen/CGDecl.cpp (+9-3)
- (modified) clang/lib/CodeGen/CGExpr.cpp (+59-2)
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+21-3)
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+67)
- (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+130)
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+20)
- (modified) clang/lib/Parse/ParseDecl.cpp (+47)
- (modified) clang/lib/Sema/SemaCast.cpp (+15-1)
- (modified) clang/lib/Sema/SemaChecking.cpp (+63)
- (modified) clang/lib/Sema/SemaDecl.cpp (+13-1)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+37)
- (modified) clang/lib/Sema/SemaExpr.cpp (+14)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+5)
- (modified) clang/lib/Sema/SemaObjCProperty.cpp (+4)
- (modified) clang/lib/Sema/SemaOverload.cpp (+11)
- (modified) clang/lib/Sema/SemaType.cpp (+87)
- (modified) clang/lib/Sema/TreeTransform.h (+11)
- (modified) clang/test/AST/ast-dump-ptrauth-json.cpp (+2)
- (added) clang/test/CodeGen/ptrauth-debuginfo.c (+32)
- (added) clang/test/CodeGen/ptrauth-qualifier-function.c (+132)
- (added) clang/test/CodeGen/ptrauth-qualifier-loadstore.c (+744)
- (added) clang/test/CodeGen/ptrauth-qualifier.c (+87)
- (added) clang/test/CodeGenCXX/ptrauth-qualifier-struct.cpp (+167)
- (added) clang/test/CodeGenObjCXX/ptrauth-struct-cxx-abi.mm (+35)
- (modified) clang/test/Preprocessor/ptrauth_feature.c (+8)
- (added) clang/test/Sema/ptrauth-atomic-ops.c (+117)
- (added) clang/test/Sema/ptrauth-qualifier.c (+84)
- (added) clang/test/SemaCXX/ptrauth-qualifier.cpp (+141)
- (added) clang/test/SemaCXX/ptrauth-template-parameters.cpp (+20)
- (added) clang/test/SemaObjC/ptrauth-qualifier.m (+55)
``````````diff
diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst
index 68674f318c84f..41818d43ac687 100644
--- a/clang/docs/PointerAuthentication.rst
+++ b/clang/docs/PointerAuthentication.rst
@@ -280,6 +280,52 @@ a number of different tests.
normal interface. This may be true even on targets where pointer
authentication is not enabled by default.
+__ptrauth Qualifier
+^^^^^^^^^^^^^^^^^^^
+
+``__ptrauth(key, address, discriminator)`` is an extended type
+qualifier which causes so-qualified objects to hold pointers signed using the
+specified schema rather than the default schema for such types.
+
+In the current implementation in Clang, the qualified type must be a C pointer
+type, either to a function or to an object. It currently cannot be an
+Objective-C pointer type, a C++ reference type, or a block pointer type; these
+restrictions may be lifted in the future.
+
+The qualifier's operands are as follows:
+
+- ``key`` - an expression evaluating to a key value from ``<ptrauth.h>``; must
+ be a constant expression
+
+- ``address`` - whether to use address diversity (1) or not (0); must be
+ a constant expression with one of these two values
+
+- ``discriminator`` - a constant discriminator; must be a constant expression
+
+See `Discriminators`_ for more information about discriminators.
+
+Currently the operands must be constant-evaluable even within templates. In the
+future this restriction may be lifted to allow value-dependent expressions as
+long as they instantiate to a constant expression.
+
+Consistent with the ordinary C/C++ rule for parameters, top-level ``__ptrauth``
+qualifiers on a parameter (after parameter type adjustment) are ignored when
+deriving the type of the function. The parameter will be passed using the
+default ABI for the unqualified pointer type.
+
+If ``x`` is an object of type ``__ptrauth(key, address, discriminator) T``,
+then the signing schema of the value stored in ``x`` is a key of ``key`` and
+a discriminator determined as follows:
+
+- if ``address`` is 0, then the discriminator is ``discriminator``;
+
+- if ``address`` is 1 and ``discriminator`` is 0, then the discriminator is
+ ``&x``; otherwise
+
+- if ``address`` is 1 and ``discriminator`` is non-zero, then the discriminator
+ is ``ptrauth_blend_discriminator(&x, discriminator)``; see
+ `ptrauth_blend_discriminator`_.
+
``<ptrauth.h>``
~~~~~~~~~~~~~~~
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 72723c7c56e07..2fb17f352f1b3 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -307,6 +307,12 @@ class PointerAuthQualifier {
return Result;
}
+ std::string getAsString() const;
+ std::string getAsString(const PrintingPolicy &Policy) const;
+
+ bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const;
+ void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
+
void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
};
@@ -556,7 +562,7 @@ class Qualifiers {
bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
LangAS getAddressSpace() const {
- return static_cast<LangAS>(Mask >> AddressSpaceShift);
+ return static_cast<LangAS>((Mask & AddressSpaceMask) >> AddressSpaceShift);
}
bool hasTargetSpecificAddressSpace() const {
return isTargetAddressSpace(getAddressSpace());
@@ -815,6 +821,9 @@ class Qualifiers {
static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
"PointerAuthQualifier must be 32 bits");
+ static constexpr uint64_t PtrAuthShift = 32;
+ static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;
+
static constexpr uint64_t UMask = 0x8;
static constexpr uint64_t UShift = 3;
static constexpr uint64_t GCAttrMask = 0x30;
@@ -822,10 +831,8 @@ class Qualifiers {
static constexpr uint64_t LifetimeMask = 0x1C0;
static constexpr uint64_t LifetimeShift = 6;
static constexpr uint64_t AddressSpaceMask =
- ~(CVRMask | UMask | GCAttrMask | LifetimeMask);
+ ~(CVRMask | UMask | GCAttrMask | LifetimeMask | PtrAuthMask);
static constexpr uint64_t AddressSpaceShift = 9;
- static constexpr uint64_t PtrAuthShift = 32;
- static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;
};
class QualifiersAndAtomic {
@@ -1460,6 +1467,12 @@ class QualType {
return getQualifiers().getPointerAuth();
}
+ bool hasAddressDiscriminatedPointerAuth() const {
+ if (PointerAuthQualifier ptrauth = getPointerAuth())
+ return ptrauth.isAddressDiscriminated();
+ return false;
+ }
+
enum PrimitiveDefaultInitializeKind {
/// The type does not fall into any of the following categories. Note that
/// this case is zero-valued so that values of this enum can be used as a
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 4825979a974d2..f9b447e85707d 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3339,6 +3339,14 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
let SimpleHandler = 1;
}
+def PointerAuth : TypeAttr {
+ let Spellings = [CustomKeyword<"__ptrauth">];
+ let Args = [IntArgument<"Key">,
+ BoolArgument<"AddressDiscriminated", 1>,
+ IntArgument<"ExtraDiscriminator", 1>];
+ let Documentation = [PtrAuthDocs];
+}
+
def Unused : InheritableAttr {
let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
C23<"", "maybe_unused", 202106>];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 99738812c8157..e7b990a2abb8c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1758,6 +1758,34 @@ Also see the documentation for `@available
}];
}
+def PtrAuthDocs : Documentation {
+ let Category = DocCatVariable;
+ let Heading = "__ptrauth, __ptrauth_restricted_intptr";
+ let Content = [{
+The ``__ptrauth`` qualifier allows the programmer to directly control
+how pointers are signed when they are stored in a particular variable.
+This can be used to strengthen the default protections of pointer
+authentication and make it more difficult for an attacker to escalate
+an ability to alter memory into full control of a process.
+
+.. code-block:: c
+
+ #include <ptrauth.h>
+
+ typedef void (*my_callback)(const void*);
+ my_callback __ptrauth(ptrauth_key_process_dependent_code, 1, 0xe27a) callback;
+
+The first argument to ``__ptrauth`` is the name of the signing key.
+Valid key names for the target are defined in ``<ptrauth.h>``.
+
+The second argument to ``__ptrauth`` is a flag (0 or 1) specifying whether
+the object should use address discrimination.
+
+The third argument to ``__ptrauth`` is a small non-negative integer
+which allows additional discrimination between objects.
+ }];
+}
+
def ExternalSourceSymbolDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 810abe4f23e31..db07874ffcbbf 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -956,6 +956,25 @@ def err_ptrauth_indirect_goto_addrlabel_arithmetic : Error<
"%select{subtraction|addition}0 of address-of-label expressions is not "
"supported with ptrauth indirect gotos">;
+// __ptrauth qualifier
+def err_ptrauth_qualifier_invalid : Error<
+ "%select{return types|parameter types|properties}2 may not be qualified with %select{__ptrauth|__ptrauth_restricted_intptr}1; type is %0">;
+def err_ptrauth_qualifier_cast : Error<
+ "cast types may not be qualified with __ptrauth; type is %0">;
+def err_ptrauth_qualifier_nonpointer : Error<
+ "__ptrauth qualifier may only be applied to pointer types; type here is %0">;
+def err_ptrauth_qualifier_redundant : Error<
+ "type %0 is already %1-qualified">;
+def err_ptrauth_qualifier_bad_arg_count : Error<
+ "%0 qualifier must take between 1 and 3 arguments">;
+def err_ptrauth_arg_not_ice : Error<
+ "argument to __ptrauth must be an integer constant expression">;
+def err_ptrauth_address_discrimination_invalid : Error<
+ "address discrimination flag for __ptrauth must be 0 or 1; value is %0">;
+def err_ptrauth_extra_discriminator_invalid : Error<
+ "extra discriminator for __ptrauth must be between "
+ "0 and %1; value is %0">;
+
/// main()
// static main() is not an error in C, just in C++.
def warn_static_main : Warning<"'main' should not be declared static">,
@@ -3870,7 +3889,8 @@ def note_cannot_use_trivial_abi_reason : Note<
"its copy constructors and move constructors are all deleted|"
"it is polymorphic|"
"it has a base of a non-trivial class type|it has a virtual base|"
- "it has a __weak field|it has a field of a non-trivial class type}1">;
+ "it has a __weak field|it has a field of a non-trivial class type|"
+ "it has an address-discriminated __ptrauth field}1">;
// Availability attribute
def warn_availability_unknown_platform : Warning<
@@ -4927,6 +4947,10 @@ def note_ovl_candidate_bad_ownership : Note<
"%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}4 ownership,"
" but parameter has %select{no|__unsafe_unretained|__strong|__weak|"
"__autoreleasing}5 ownership">;
+def note_ovl_candidate_bad_ptrauth : Note<
+ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
+ "%ordinal8 argument (%3) has %select{no ptrauth|%5}4 qualifier,"
+ " but parameter has %select{no ptrauth|%7}6 qualifier">;
def note_ovl_candidate_bad_cvr_this : Note<
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
"'this' argument has type %3, but method is not marked "
@@ -6005,7 +6029,7 @@ def note_deleted_special_member_class_subobject : Note<
"%select{default|corresponding|default|default|default}4 constructor}0|"
"destructor}5"
"%select{||s||}4"
- "|is an ObjC pointer}6">;
+ "|is an ObjC pointer|has an address-discriminated ptrauth qualifier}6">;
def note_deleted_default_ctor_uninit_field : Note<
"%select{default constructor of|constructor inherited by}0 "
"%1 is implicitly deleted because field %2 of "
@@ -8811,6 +8835,19 @@ def err_typecheck_incompatible_ownership : Error<
"sending to parameter of different type}0,1"
"|%diff{casting $ to type $|casting between types}0,1}2"
" changes retain/release properties of pointer">;
+def err_typecheck_incompatible_ptrauth : Error<
+ "%select{%diff{assigning $ to $|assigning to different types}1,0"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " changes pointer-authentication of pointee type">;
def err_typecheck_comparison_of_distinct_blocks : Error<
"comparison of distinct block types%diff{ ($ and $)|}0,1">;
@@ -8939,6 +8976,9 @@ def err_atomic_op_needs_non_const_atomic : Error<
def err_atomic_op_needs_non_const_pointer : Error<
"address argument to atomic operation must be a pointer to non-const "
"type (%0 invalid)">;
+def err_atomic_op_needs_non_address_discriminated_pointer : Error<
+ "address argument to %select{atomic|__sync}0 operation must be a pointer to a non address discriminated "
+ "type (%1 invalid)">;
def err_atomic_op_needs_trivial_copy : Error<
"address argument to atomic operation must be a pointer to a "
"trivially-copyable type (%0 invalid)">;
@@ -9205,6 +9245,8 @@ def ext_typecheck_cond_pointer_integer_mismatch : ExtWarn<
"pointer/integer type mismatch in conditional expression"
"%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"conditional-type-mismatch">>;
+def err_typecheck_cond_incompatible_ptrauth : Error<
+ "__ptrauth qualification mismatch%diff{ ($ and $)|}0,1">;
def err_typecheck_choose_expr_requires_constant : Error<
"'__builtin_choose_expr' requires a constant expression">;
def warn_unused_expr : Warning<"expression result unused">,
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index dc71ef8f98692..6853a7969e929 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -104,6 +104,7 @@ FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics)
+FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics)
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 8c54661e65cf4..68a214452e28b 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -346,6 +346,7 @@ KEYWORD(_Thread_local , KEYALL)
KEYWORD(__func__ , KEYALL)
KEYWORD(__objc_yes , KEYALL)
KEYWORD(__objc_no , KEYALL)
+KEYWORD(__ptrauth , KEYALL)
// C++ 2.11p1: Keywords.
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 35bb1a19d40f0..e3049914289bd 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3151,6 +3151,8 @@ class Parser : public CodeCompletionHandler {
SourceLocation *endLoc = nullptr);
ExprResult ParseExtIntegerArgument();
+ void ParsePtrauthQualifier(ParsedAttributes &Attrs);
+
VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const;
VirtSpecifiers::Specifier isCXX11VirtSpecifier() const {
return isCXX11VirtSpecifier(Tok);
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7bfdaaae45a93..673862e4711a4 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3460,6 +3460,17 @@ class Sema final : public SemaBase {
bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key);
+ enum PointerAuthDiscArgKind {
+ // Address discrimination argument of __ptrauth.
+ PADAK_AddrDiscPtrAuth,
+
+ // Extra discriminator argument of __ptrauth.
+ PADAK_ExtraDiscPtrAuth,
+ };
+
+ bool checkPointerAuthDiscriminatorArg(Expr *Arg, PointerAuthDiscArgKind Kind,
+ unsigned &IntVal);
+
/// Diagnose function specifiers on a declaration of an identifier that
/// does not identify a function.
void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a465cdfcf3c89..c1dc730eaa2d5 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -11046,6 +11046,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer,
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
LQuals.getAddressSpace() != RQuals.getAddressSpace() ||
LQuals.getObjCLifetime() != RQuals.getObjCLifetime() ||
+ !LQuals.getPointerAuth().isEquivalent(RQuals.getPointerAuth()) ||
LQuals.hasUnaligned() != RQuals.hasUnaligned())
return {};
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index b573c2713a3aa..c2c550076ea07 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1072,6 +1072,33 @@ void CXXRecordDecl::addedMember(Decl *D) {
} else if (!T.isCXX98PODType(Context))
data().PlainOldData = false;
+ // If a class has an address-discriminated signed pointer member, it is a
+ // non-POD type and its copy constructor, move constructor, copy assignment
+ // operator, move assignment operator are non-trivial.
+ if (PointerAuthQualifier Q = T.getPointerAuth()) {
+ if (Q.isAddressDiscriminated()) {
+ struct DefinitionData &Data = data();
+ Data.PlainOldData = false;
+ Data.HasTrivialSpecialMembers &=
+ ~(SMF_CopyConstructor | SMF_MoveConstructor | SMF_CopyAssignment |
+ SMF_MoveAssignment);
+ setArgPassingRestrictions(RecordArgPassingKind::CanNeverPassInRegs);
+
+ // Copy/move constructors/assignment operators of a union are deleted by
+ // default if it has an address-discriminated ptrauth field.
+ if (isUnion()) {
+ data().DefaultedCopyConstructorIsDeleted = true;
+ data().DefaultedMoveConstructorIsDeleted = true;
+ data().DefaultedCopyAssignmentIsDeleted = true;
+ data().DefaultedMoveAssignmentIsDeleted = true;
+ data().NeedOverloadResolutionForCopyConstructor = true;
+ data().NeedOverloadResolutionForMoveConstructor = true;
+ data().NeedOverloadResolutionForCopyAssignment = true;
+ data().NeedOverloadResolutionForMoveAssignment = true;
+ }
+ }
+ }
+
if (T->isReferenceType()) {
if (!Field->hasInClassInitializer())
data().HasUninitializedReferenceMember = true;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index d46d621d4c7d4..0e95517bfa424 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2822,6 +2822,26 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
if (Quals.hasUnaligned())
mangleVendorQualifier("__unaligned");
+ // __ptrauth. Note that this is parameterized.
+ if (PointerAuthQualifier PtrAuth = Quals.getPointerAuth()) {
+ mangleVendorQualifier("__ptrauth");
+ // For now, since we only allow non-dependent arguments, we can just
+ // inline the mangling of those arguments as literals. We treat the
+ // key and extra-discriminator arguments as 'unsigned int' and the
+ // address-discriminated argument as 'bool'.
+ Out << "I"
+ "Lj"
+ << PtrAuth.getKey()
+ << "E"
+ "Lb"
+ << unsigned(PtrAuth.isAddressDiscriminated())
+ << "E"
+ "Lj"
+ << PtrAuth.getExtraDiscriminator()
+ << "E"
+ "E";
+ }
+
// Remaining ARC ownership qualifiers.
switch (Quals.getObjCLifetime()) {
case Qualifiers::OCL_None:
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index ffec3ef9d2269..542cf7502e20e 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1950,6 +1950,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::Ptr64:
case attr::SPtr:
case attr::UPtr:
+ case attr::PointerAuth:
case attr::AddressSpace:
case attr::CmseNSCall:
case attr::AnnotateType:
@@ -2413,6 +2414,33 @@ void clang::printTemplateArgumentList(raw_ostream &OS,
printTo(OS, Args, Policy, TPL, /*isPack*/ false, /*parmIndex*/ 0);
}
+std::string PointerAuthQualifier::getAsString() const {
+ LangOptions LO;
+ return getAsString(PrintingPolicy(LO));
+}
+
+std::string PointerAuthQualifier::getAsString(const PrintingPolicy &P) const {
+ SmallString<64> Buf;
+ llvm::raw_svector_ostream StrOS(Buf);
+ print(StrOS, P);
+ return StrOS.str().str();
+}
+
+bool PointerAuthQualifier::isEmptyWhenPrinted(const PrintingPolicy &P) const {
+ return !isPresent();
+}
+
+void PointerAuthQualifier::print(raw_ostream &OS,
+ const PrintingPolicy &P) const {
+ if (!isPresent())
+ return;
+
+ OS << "__ptrauth(";
+ OS << getKey();
+ OS << "," << unsigned(isAddressDiscriminated()) << ","
+ << getExtraDiscriminator() << ")";
+}
+
std::string Qualifiers::getAsString() const {
LangOptions LO;
return getAsString(PrintingPolicy(LO));
@@ -2442,6 +2470,10 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
if (!(lifetime == Qualifiers::OCL_Strong && Policy.Suppres...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/100830
More information about the cfe-commits
mailing list