https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/84384
>From ef23d427b48687b62da9e1062886ddfcc1649b6a Mon Sep 17 00:00:00 2001 From: John McCall <rjmcc...@apple.com> Date: Mon, 16 Dec 2019 20:31:25 -0500 Subject: [PATCH 1/8] Abstract serialization fixes for the Apple Clang changes. --- clang/include/clang/AST/AbstractBasicReader.h | 4 ++-- clang/include/clang/AST/AbstractBasicWriter.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index 1f2797cc701458..ab036f1d445acc 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -213,9 +213,9 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> { } Qualifiers readQualifiers() { - static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t), + static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t), "update this if the value size changes"); - uint32_t value = asImpl().readUInt32(); + uint64_t value = asImpl().readUInt64(); return Qualifiers::fromOpaqueValue(value); } diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index 07afa388de2c17..8e42fcaad1d388 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -196,9 +196,9 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> { } void writeQualifiers(Qualifiers value) { - static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t), + static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t), "update this if the value size changes"); - asImpl().writeUInt32(value.getAsOpaqueValue()); + asImpl().writeUInt64(value.getAsOpaqueValue()); } void writeExceptionSpecInfo( >From 9e296a1a69158419960c265f12f52523db0c8e2a Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Thu, 7 Mar 2024 15:34:24 +0300 Subject: [PATCH 2/8] [clang] Define `PointerAuthenticationMode` enum --- clang/include/clang/Basic/LangOptions.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 862952d336ef31..6fe7472d8ad0ca 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -57,6 +57,13 @@ enum class ShaderStage { Invalid, }; +enum class PointerAuthenticationMode : unsigned { + None, + Strip, + SignAndStrip, + SignAndAuth +}; + /// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// this large collection of bitfields is a trivial class type. class LangOptionsBase { >From 71d7760aa9cc459d7bc0365fa079f64cb5704c96 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Thu, 7 Mar 2024 15:31:03 +0300 Subject: [PATCH 3/8] [clang] Define `PointerAuthQualifier` class Includes changes from the following commits from the branch https://github.com/ahmedbougacha/llvm-project/tree/eng/arm64e-upstream-llvmorg - Initial support https://github.com/ahmedbougacha/llvm-project/commit/cc7ba7eb1814e9b254c7d94aa0b78cb0e21acfc5 - ObjC isa signing https://github.com/ahmedbougacha/llvm-project/commit/c9ce0d408f1d9aeffc7b86256334220aec6de5a3 Also applies a fix from https://github.com/access-softek/llvm-project/pull/75 Co-authored-by: Ahmed Bougacha <ah...@bougacha.org> --- clang/include/clang/AST/Type.h | 215 +++++++++++++++++- .../include/clang/Basic/PointerAuthOptions.h | 23 ++ 2 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 clang/include/clang/Basic/PointerAuthOptions.h diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 1942b0e67f65a3..1741a3017f7280 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -25,8 +25,10 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/PointerAuthOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" @@ -138,6 +140,165 @@ using CanQualType = CanQual<Type>; #define TYPE(Class, Base) class Class##Type; #include "clang/AST/TypeNodes.inc" +/// Pointer-authentication qualifiers. +class PointerAuthQualifier { + enum : uint32_t { + EnabledShift = 0, + EnabledBits = 1, + EnabledMask = 1 << EnabledShift, + AddressDiscriminatedShift = EnabledShift + EnabledBits, + AddressDiscriminatedBits = 1, + AddressDiscriminatedMask = 1 << AddressDiscriminatedShift, + AuthenticationModeShift = + AddressDiscriminatedShift + AddressDiscriminatedBits, + AuthenticationModeBits = 2, + AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1) + << AuthenticationModeShift, + IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits, + IsaPointerBits = 1, + IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift, + AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits, + AuthenticatesNullValuesBits = 1, + AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1) + << AuthenticatesNullValuesShift, + KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits, + KeyBits = 10, + KeyMask = ((1 << KeyBits) - 1) << KeyShift, + DiscriminatorShift = KeyShift + KeyBits, + DiscriminatorBits = 16, + DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift, + }; + + // bits: |0 |1 |2..3 |4 | + // |Enabled|Address|AuthenticationMode|ISA pointer| + // bits: |5 |6..15| 16...31 | + // |AuthenticatesNull|Key |Discriminator| + uint32_t Data; + + static_assert((EnabledBits + AddressDiscriminatedBits + + AuthenticationModeBits + IsaPointerBits + + AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) == + 32, + "PointerAuthQualifier should be exactly 32 bits"); + static_assert((EnabledMask + AddressDiscriminatedMask + + AuthenticationModeMask + IsaPointerMask + + AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) == + 0xFFFFFFFF, + "All masks should cover the entire bits"); + static_assert((EnabledMask ^ AddressDiscriminatedMask ^ + AuthenticationModeMask ^ IsaPointerMask ^ + AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) == + 0xFFFFFFFF, + "All masks should cover the entire bits"); + + PointerAuthQualifier(unsigned key, bool isAddressDiscriminated, + unsigned extraDiscriminator, + PointerAuthenticationMode authenticationMode, + bool isIsaPointer, bool authenticatesNullValues) + : Data(EnabledMask | + (isAddressDiscriminated + ? static_cast<uint32_t>(AddressDiscriminatedMask) + : 0) | + (key << KeyShift) | + (unsigned(authenticationMode) << AuthenticationModeShift) | + (extraDiscriminator << DiscriminatorShift) | + (isIsaPointer << IsaPointerShift) | + (authenticatesNullValues << AuthenticatesNullValuesShift)) { + assert(key <= KeyNoneInternal); + assert(extraDiscriminator <= MaxDiscriminator); + } + +public: + enum { + KeyNoneInternal = (1u << KeyBits) - 1, + + /// The maximum supported pointer-authentication key. + MaxKey = KeyNoneInternal - 1, + + /// The maximum supported pointer-authentication discriminator. + MaxDiscriminator = (1u << DiscriminatorBits) - 1 + }; + +public: + PointerAuthQualifier() : Data(0) {} + + static PointerAuthQualifier + Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator, + PointerAuthenticationMode authenticationMode, bool isIsaPointer, + bool authenticatesNullValues) { + if (key == PointerAuthKeyNone) + key = KeyNoneInternal; + assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value"); + return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator, + authenticationMode, isIsaPointer, + authenticatesNullValues); + } + + bool isPresent() const { + return getAuthenticationMode() != PointerAuthenticationMode::None; + } + + explicit operator bool() const { return isPresent(); } + + unsigned getKey() const { + assert(isPresent()); + return (Data & KeyMask) >> KeyShift; + } + + bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; } + + bool isAddressDiscriminated() const { + assert(isPresent()); + return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift; + } + + unsigned getExtraDiscriminator() const { + assert(isPresent()); + return (Data >> DiscriminatorShift); + } + + PointerAuthenticationMode getAuthenticationMode() const { + return PointerAuthenticationMode((Data & AuthenticationModeMask) >> + AuthenticationModeShift); + } + + bool isIsaPointer() const { + assert(isPresent()); + return (Data & IsaPointerMask) >> IsaPointerShift; + } + + bool authenticatesNullValues() const { + assert(isPresent()); + return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift; + } + + PointerAuthQualifier withoutKeyNone() const { + return hasKeyNone() ? PointerAuthQualifier() : *this; + } + + friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) { + return Lhs.Data == Rhs.Data; + } + friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) { + return Lhs.Data != Rhs.Data; + } + + bool isEquivalent(PointerAuthQualifier Other) const { + return withoutKeyNone() == Other.withoutKeyNone(); + } + + uint32_t getAsOpaqueValue() const { return Data; } + + // Deserialize pointer-auth qualifiers from an opaque representation. + static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) { + PointerAuthQualifier result; + result.Data = opaque; + return result; + } + + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); } +}; + /// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: /// * C99: const, volatile, and restrict @@ -193,19 +354,27 @@ class Qualifiers { FastMask = (1 << FastWidth) - 1 }; + Qualifiers() : Mask(0), PtrAuth() {} + /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { + Qualifiers Q; + if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) { + Q.setPointerAuth(L.getPointerAuth().withoutKeyNone()); + PointerAuthQualifier Empty; + L.setPointerAuth(Empty); + R.setPointerAuth(Empty); + } + // If both are only CVR-qualified, bit operations are sufficient. if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) { - Qualifiers Q; Q.Mask = L.Mask & R.Mask; L.Mask &= ~Q.Mask; R.Mask &= ~Q.Mask; return Q; } - Qualifiers Q; unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers(); Q.addCVRQualifiers(CommonCRV); L.removeCVRQualifiers(CommonCRV); @@ -250,15 +419,16 @@ class Qualifiers { } // Deserialize qualifiers from an opaque representation. - static Qualifiers fromOpaqueValue(unsigned opaque) { + static Qualifiers fromOpaqueValue(uint64_t opaque) { Qualifiers Qs; - Qs.Mask = opaque; + Qs.Mask = uint32_t(opaque); + Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32)); return Qs; } // Serialize these qualifiers into an opaque representation. - unsigned getAsOpaqueValue() const { - return Mask; + uint64_t getAsOpaqueValue() const { + return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32); } bool hasConst() const { return Mask & Const; } @@ -406,6 +576,10 @@ class Qualifiers { setAddressSpace(space); } + PointerAuthQualifier getPointerAuth() const { return PtrAuth; } + void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; } + void removePtrAuth() { PtrAuth = PointerAuthQualifier(); } + // Fast qualifiers are those that can be allocated directly // on a QualType object. bool hasFastQualifiers() const { return getFastQualifiers(); } @@ -428,7 +602,7 @@ class Qualifiers { /// Return true if the set contains any qualifiers which require an ExtQuals /// node to be allocated. - bool hasNonFastQualifiers() const { return Mask & ~FastMask; } + bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; } Qualifiers getNonFastQualifiers() const { Qualifiers Quals = *this; Quals.setFastQualifiers(0); @@ -436,8 +610,8 @@ class Qualifiers { } /// Return true if the set contains any qualifiers. - bool hasQualifiers() const { return Mask; } - bool empty() const { return !Mask; } + bool hasQualifiers() const { return Mask || PtrAuth; } + bool empty() const { return !hasQualifiers(); } /// Add the qualifiers from the given set to this set. void addQualifiers(Qualifiers Q) { @@ -454,6 +628,9 @@ class Qualifiers { if (Q.hasObjCLifetime()) addObjCLifetime(Q.getObjCLifetime()); } + + if (Q.PtrAuth) + PtrAuth = Q.PtrAuth; } /// Remove the qualifiers from the given set from this set. @@ -471,6 +648,9 @@ class Qualifiers { if (getAddressSpace() == Q.getAddressSpace()) removeAddressSpace(); } + + if (PtrAuth == Q.PtrAuth) + PtrAuth = PointerAuthQualifier(); } /// Add the qualifiers from the given set to this set, given that @@ -482,7 +662,10 @@ class Qualifiers { !hasObjCGCAttr() || !qs.hasObjCGCAttr()); assert(getObjCLifetime() == qs.getObjCLifetime() || !hasObjCLifetime() || !qs.hasObjCLifetime()); + assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth); Mask |= qs.Mask; + if (qs.PtrAuth) + PtrAuth = qs.PtrAuth; } /// Returns true if address space A is equal to or a superset of B. @@ -535,6 +718,8 @@ class Qualifiers { // be changed. (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || !other.hasObjCGCAttr()) && + // Pointer-auth qualifiers must match exactly. + PtrAuth == other.PtrAuth && // ObjC lifetime qualifiers must match exactly. getObjCLifetime() == other.getObjCLifetime() && // CVR qualifiers may subset. @@ -567,8 +752,12 @@ class Qualifiers { /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; - bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } - bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } + bool operator==(Qualifiers Other) const { + return Mask == Other.Mask && PtrAuth == Other.PtrAuth; + } + bool operator!=(Qualifiers Other) const { + return Mask != Other.Mask || PtrAuth != Other.PtrAuth; + } explicit operator bool() const { return hasQualifiers(); } @@ -606,6 +795,7 @@ class Qualifiers { void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); + PtrAuth.Profile(ID); } private: @@ -613,6 +803,9 @@ class Qualifiers { // |C R V|U|GCAttr|Lifetime|AddressSpace| uint32_t Mask = 0; + PointerAuthQualifier PtrAuth; + static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t), + "PointerAuthQualifier must be 32 bits"); static const uint32_t UMask = 0x8; static const uint32_t UShift = 3; static const uint32_t GCAttrMask = 0x30; diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h new file mode 100644 index 00000000000000..c69847ac704a41 --- /dev/null +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -0,0 +1,23 @@ +//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines options for configuring pointer-auth technologies +// like ARMv8.3. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H +#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H + +namespace clang { + +constexpr int PointerAuthKeyNone = -1; + +} // end namespace clang + +#endif >From cbfde2159c0af8b472ab296c37dc1adf9fc4ad91 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Thu, 7 Mar 2024 17:54:20 +0300 Subject: [PATCH 4/8] [clang] Support `PointerAuthQualifier` in `QualType` --- clang/include/clang/AST/ASTContext.h | 10 ++++++++++ clang/include/clang/AST/Type.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ff6b64c7f72d57..4fd214592d1f27 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2182,6 +2182,16 @@ class ASTContext : public RefCountedBase<ASTContext> { return getQualifiedType(type.getUnqualifiedType(), Qs); } + /// \brief Return a type with the given __ptrauth qualifier. + QualType getPointerAuthType(QualType type, PointerAuthQualifier pointerAuth) { + assert(!type.getPointerAuth()); + assert(pointerAuth); + + Qualifiers qs; + qs.setPointerAuth(pointerAuth); + return getQualifiedType(type, qs); + } + unsigned char getFixedPointScale(QualType Ty) const; unsigned char getFixedPointIBits(QualType Ty) const; llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 1741a3017f7280..48a51dd851ac36 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1434,6 +1434,10 @@ class QualType { // true when Type is objc's weak and weak is enabled but ARC isn't. bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const; + PointerAuthQualifier getPointerAuth() const { + return getQualifiers().getPointerAuth(); + } + 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 >From 3517033bd3a8b676abd649562bcfc7eb4d278d09 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Mon, 8 Apr 2024 18:12:18 +0300 Subject: [PATCH 5/8] Address review comments & enhance code style --- clang/include/clang/AST/ASTContext.h | 10 ++-- clang/include/clang/AST/Type.h | 57 ++++++++++--------- .../include/clang/Basic/PointerAuthOptions.h | 2 +- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index f77726f332ea03..eeac5961b415b8 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2197,13 +2197,13 @@ class ASTContext : public RefCountedBase<ASTContext> { } /// \brief Return a type with the given __ptrauth qualifier. - QualType getPointerAuthType(QualType type, PointerAuthQualifier pointerAuth) { - assert(!type.getPointerAuth()); - assert(pointerAuth); + QualType getPointerAuthType(QualType Ty, PointerAuthQualifier PointerAuth) { + assert(!Ty.getPointerAuth()); + assert(PointerAuth); Qualifiers qs; - qs.setPointerAuth(pointerAuth); - return getQualifiedType(type, qs); + qs.setPointerAuth(PointerAuth); + return getQualifiedType(Ty, qs); } unsigned char getFixedPointScale(QualType Ty) const; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e5f11174cca9bc..4dd532c2420206 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -176,6 +176,8 @@ class PointerAuthQualifier { // |AuthenticatesNull|Key |Discriminator| uint32_t Data; + // The following static assertions check that each of the 32 bits is present + // exactly in one of the constants. static_assert((EnabledBits + AddressDiscriminatedBits + AuthenticationModeBits + IsaPointerBits + AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) == @@ -192,21 +194,22 @@ class PointerAuthQualifier { 0xFFFFFFFF, "All masks should cover the entire bits"); - PointerAuthQualifier(unsigned key, bool isAddressDiscriminated, - unsigned extraDiscriminator, - PointerAuthenticationMode authenticationMode, - bool isIsaPointer, bool authenticatesNullValues) + PointerAuthQualifier(unsigned Key, bool IsAddressDiscriminated, + unsigned ExtraDiscriminator, + PointerAuthenticationMode AuthenticationMode, + bool IsIsaPointer, bool AuthenticatesNullValues) : Data(EnabledMask | - (isAddressDiscriminated - ? static_cast<uint32_t>(AddressDiscriminatedMask) + (IsAddressDiscriminated + ? llvm::to_underlying(AddressDiscriminatedMask) : 0) | - (key << KeyShift) | - (unsigned(authenticationMode) << AuthenticationModeShift) | - (extraDiscriminator << DiscriminatorShift) | - (isIsaPointer << IsaPointerShift) | - (authenticatesNullValues << AuthenticatesNullValuesShift)) { - assert(key <= KeyNoneInternal); - assert(extraDiscriminator <= MaxDiscriminator); + (Key << KeyShift) | + (llvm::to_underlying(AuthenticationMode) + << AuthenticationModeShift) | + (ExtraDiscriminator << DiscriminatorShift) | + (IsIsaPointer << IsaPointerShift) | + (AuthenticatesNullValues << AuthenticatesNullValuesShift)) { + assert(Key <= KeyNoneInternal); + assert(ExtraDiscriminator <= MaxDiscriminator); } public: @@ -224,15 +227,15 @@ class PointerAuthQualifier { PointerAuthQualifier() : Data(0) {} static PointerAuthQualifier - Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator, - PointerAuthenticationMode authenticationMode, bool isIsaPointer, - bool authenticatesNullValues) { - if (key == PointerAuthKeyNone) - key = KeyNoneInternal; - assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value"); - return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator, - authenticationMode, isIsaPointer, - authenticatesNullValues); + Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, + PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer, + bool AuthenticatesNullValues) { + if (Key == PointerAuthKeyNone) + Key = KeyNoneInternal; + assert(Key <= KeyNoneInternal && "out-of-range key value"); + return PointerAuthQualifier(Key, IsAddressDiscriminated, ExtraDiscriminator, + AuthenticationMode, IsIsaPointer, + AuthenticatesNullValues); } bool isPresent() const { @@ -291,9 +294,9 @@ class PointerAuthQualifier { uint32_t getAsOpaqueValue() const { return Data; } // Deserialize pointer-auth qualifiers from an opaque representation. - static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) { + static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) { PointerAuthQualifier result; - result.Data = opaque; + result.Data = Opaque; return result; } @@ -420,10 +423,10 @@ class Qualifiers { } // Deserialize qualifiers from an opaque representation. - static Qualifiers fromOpaqueValue(uint64_t opaque) { + static Qualifiers fromOpaqueValue(uint64_t Opaque) { Qualifiers Qs; - Qs.Mask = uint32_t(opaque); - Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32)); + Qs.Mask = uint32_t(Opaque); + Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(Opaque >> 32)); return Qs; } diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h index c69847ac704a41..e5cdcc31ebfb70 100644 --- a/clang/include/clang/Basic/PointerAuthOptions.h +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -16,7 +16,7 @@ namespace clang { -constexpr int PointerAuthKeyNone = -1; +constexpr unsigned PointerAuthKeyNone = -1; } // end namespace clang >From cfb3afe19c698aaf41fb7b492503081989896434 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Tue, 16 Apr 2024 20:01:17 +0300 Subject: [PATCH 6/8] Address review comments --- clang/include/clang/AST/ASTContext.h | 6 +++--- clang/include/clang/AST/Type.h | 12 +++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 52eaa5b36fead3..23959d4453ca54 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2201,9 +2201,9 @@ class ASTContext : public RefCountedBase<ASTContext> { assert(!Ty.getPointerAuth()); assert(PointerAuth); - Qualifiers qs; - qs.setPointerAuth(PointerAuth); - return getQualifiedType(Ty, qs); + Qualifiers Qs; + Qs.setPointerAuth(PointerAuth); + return getQualifiedType(Ty, Qs); } unsigned char getFixedPointScale(QualType Ty) const; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 4dd532c2420206..30b23de23f4c66 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -174,7 +174,7 @@ class PointerAuthQualifier { // |Enabled|Address|AuthenticationMode|ISA pointer| // bits: |5 |6..15| 16...31 | // |AuthenticatesNull|Key |Discriminator| - uint32_t Data; + uint32_t Data = 0; // The following static assertions check that each of the 32 bits is present // exactly in one of the constants. @@ -224,7 +224,7 @@ class PointerAuthQualifier { }; public: - PointerAuthQualifier() : Data(0) {} + PointerAuthQualifier() = default; static PointerAuthQualifier Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, @@ -295,9 +295,9 @@ class PointerAuthQualifier { // Deserialize pointer-auth qualifiers from an opaque representation. static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) { - PointerAuthQualifier result; - result.Data = Opaque; - return result; + PointerAuthQualifier Result; + Result.Data = Opaque; + return Result; } void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); } @@ -358,8 +358,6 @@ class Qualifiers { FastMask = (1 << FastWidth) - 1 }; - Qualifiers() : Mask(0), PtrAuth() {} - /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { >From df81082d6f0210b02e72a3237ab7c03715d23488 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Tue, 16 Apr 2024 20:11:22 +0300 Subject: [PATCH 7/8] Do not use `uint32_t(Opaque)` for getting 32 upper bits of `Opaque` --- clang/include/clang/AST/Type.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 30b23de23f4c66..6cae078d89e5b9 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -52,6 +52,7 @@ #include <cstddef> #include <cstdint> #include <cstring> +#include <limits> #include <optional> #include <string> #include <type_traits> @@ -423,8 +424,9 @@ class Qualifiers { // Deserialize qualifiers from an opaque representation. static Qualifiers fromOpaqueValue(uint64_t Opaque) { Qualifiers Qs; - Qs.Mask = uint32_t(Opaque); - Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(Opaque >> 32)); + constexpr uint32_t U32Max = std::numeric_limits<uint32_t>::max(); + Qs.Mask = Opaque & U32Max; + Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue((Opaque >> 32) & U32Max); return Qs; } >From e3cb910ebce1ffa187816a20ce52e6303799665a Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Wed, 17 Apr 2024 21:56:24 +0300 Subject: [PATCH 8/8] [clang-tidy] Use only fast qualifiers to re-construct `QualType` --- .../bugprone/EasilySwappableParametersCheck.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp index 84e99c7fafc74b..10868129e76da9 100644 --- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp @@ -967,7 +967,8 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, // Get out the qualifiers of the original type. This will always be // re-applied to the WorkType to ensure it is the same qualification as the // original From was. - auto QualifiersToApply = From.split().Quals.getAsOpaqueValue(); + auto FastQualifiersToApply = static_cast<unsigned>( + From.split().Quals.getAsOpaqueValue() & Qualifiers::FastMask); // LValue->RValue is irrelevant for the check, because it is a thing to be // done at a call site, and will be performed if need be performed. @@ -993,7 +994,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, // "const double -> double". LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Conversion between numerics.\n"); - WorkType = QualType{ToBuiltin, QualifiersToApply}; + WorkType = QualType{ToBuiltin, FastQualifiersToApply}; } const auto *FromEnum = WorkType->getAs<EnumType>(); @@ -1002,7 +1003,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, // Unscoped enumerations (or enumerations in C) convert to numerics. LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Unscoped enum to numeric.\n"); - WorkType = QualType{ToBuiltin, QualifiersToApply}; + WorkType = QualType{ToBuiltin, FastQualifiersToApply}; } else if (FromNumeric && ToEnum && ToEnum->isUnscopedEnumerationType()) { // Numeric types convert to enumerations only in C. if (Ctx.getLangOpts().CPlusPlus) { @@ -1013,7 +1014,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Numeric to unscoped enum.\n"); - WorkType = QualType{ToEnum, QualifiersToApply}; + WorkType = QualType{ToEnum, FastQualifiersToApply}; } // Check for pointer conversions. @@ -1022,14 +1023,14 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, if (FromPtr && ToPtr) { if (ToPtr->isVoidPointerType()) { LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n"); - WorkType = QualType{ToPtr, QualifiersToApply}; + WorkType = QualType{ToPtr, FastQualifiersToApply}; } const auto *FromRecordPtr = FromPtr->getPointeeCXXRecordDecl(); const auto *ToRecordPtr = ToPtr->getPointeeCXXRecordDecl(); if (isDerivedToBase(FromRecordPtr, ToRecordPtr)) { LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n"); - WorkType = QualType{ToPtr, QualifiersToApply}; + WorkType = QualType{ToPtr, FastQualifiersToApply}; } } @@ -1039,7 +1040,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, const auto *ToRecord = To->getAsCXXRecordDecl(); if (isDerivedToBase(FromRecord, ToRecord)) { LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n"); - WorkType = QualType{ToRecord->getTypeForDecl(), QualifiersToApply}; + WorkType = QualType{ToRecord->getTypeForDecl(), FastQualifiersToApply}; } if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) { @@ -1054,7 +1055,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, !ToFunctionPtr->hasNoexceptExceptionSpec()) { LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function " "pointer to non-noexcept.\n"); - WorkType = QualType{ToPtr, QualifiersToApply}; + WorkType = QualType{ToPtr, FastQualifiersToApply}; } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits