[clang] [clang-tools-extra] [PAC][clang] Define `PointerAuthQualifier` and `PointerAuthenticationMode` (PR #84384)

Daniil Kovalev via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 17 13:38:29 PDT 2024


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 <rjmccall at 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 <dkovalev at 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 <dkovalev at 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 <ahmed at 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 <dkovalev at 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 <dkovalev at 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 <dkovalev at 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 <dkovalev at 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 <dkovalev at 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};
     }
   }
 



More information about the cfe-commits mailing list