Skip to content

Revert "[clang] improve class type sugar preservation in pointers to members" #132215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

mizvekov
Copy link
Contributor

Reverts #130537

This missed updating lldb, which we didn't notice due to lack of pre-commit CI.

@mizvekov mizvekov self-assigned this Mar 20, 2025
@mizvekov mizvekov requested a review from Endilll as a code owner March 20, 2025 14:09
@llvmbot llvmbot added clang Clang issues not falling into any other category clang-tools-extra clangd clang-tidy clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:codegen IR generation bugs: mangling, exceptions, etc. clang:as-a-library libclang and C++ API clang:static analyzer clang:openmp OpenMP related changes to Clang labels Mar 20, 2025
@mizvekov mizvekov merged commit 6cd62ad into main Mar 20, 2025
9 of 13 checks passed
@mizvekov mizvekov deleted the revert-130537-users/mizvekov/clang-member-pointer-qualifier branch March 20, 2025 14:09
@llvmbot
Copy link
Member

llvmbot commented Mar 20, 2025

@llvm/pr-subscribers-clang-static-analyzer-1
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

Changes

Reverts llvm/llvm-project#130537

This missed updating lldb, which we didn't notice due to lack of pre-commit CI.


Patch is 141.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132215.diff

69 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp (+2-1)
  • (modified) clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp (+1-3)
  • (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+1-1)
  • (modified) clang/docs/ReleaseNotes.rst (-1)
  • (modified) clang/include/clang/AST/ASTContext.h (+4-3)
  • (modified) clang/include/clang/AST/ASTNodeTraverser.h (+2-5)
  • (modified) clang/include/clang/AST/CanonicalType.h (+1-1)
  • (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4-5)
  • (modified) clang/include/clang/AST/Type.h (+13-15)
  • (modified) clang/include/clang/AST/TypeLoc.h (+14-19)
  • (modified) clang/include/clang/AST/TypeProperties.td (+3-6)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4-2)
  • (modified) clang/include/clang/Sema/Sema.h (+2-9)
  • (modified) clang/lib/AST/ASTContext.cpp (+21-47)
  • (modified) clang/lib/AST/ASTImporter.cpp (+5-9)
  • (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+2-6)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+1-10)
  • (modified) clang/lib/AST/NestedNameSpecifier.cpp (-1)
  • (modified) clang/lib/AST/ODRHash.cpp (+1-1)
  • (modified) clang/lib/AST/QualTypeNames.cpp (+3-4)
  • (modified) clang/lib/AST/Type.cpp (+4-30)
  • (modified) clang/lib/AST/TypePrinter.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CGCXXABI.cpp (+1-1)
  • (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CGVTables.cpp (+3-2)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+5-5)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+3-4)
  • (modified) clang/lib/Sema/SemaAccess.cpp (+8-18)
  • (modified) clang/lib/Sema/SemaCast.cpp (+2-2)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+6-4)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+1-3)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+3-2)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+27-60)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+2-6)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+5-16)
  • (modified) clang/lib/Sema/SemaType.cpp (+100-22)
  • (modified) clang/lib/Sema/TreeTransform.h (+30-29)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+1-1)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+1-1)
  • (modified) clang/lib/Serialization/TemplateArgumentHasher.cpp (+1-3)
  • (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+1-3)
  • (modified) clang/test/AST/ast-dump-templates.cpp (-238)
  • (modified) clang/test/AST/ast-dump-types-json.cpp (+44-338)
  • (modified) clang/test/AST/attr-print-emit.cpp (+1-1)
  • (modified) clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (+5-5)
  • (modified) clang/test/CXX/class.access/p6.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg0xx.cpp (+6-6)
  • (modified) clang/test/CXX/drs/cwg13xx.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg26xx.cpp (+3-3)
  • (modified) clang/test/CXX/drs/cwg2xx.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg4xx.cpp (+1-1)
  • (modified) clang/test/CXX/drs/cwg7xx.cpp (+2-1)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (+1-1)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp (+3-3)
  • (modified) clang/test/Index/print-type.cpp (+1-1)
  • (modified) clang/test/SemaCXX/addr-of-overloaded-function.cpp (+13-13)
  • (modified) clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp (+2-2)
  • (modified) clang/test/SemaCXX/calling-conv-compat.cpp (+21-21)
  • (modified) clang/test/SemaCXX/err_init_conversion_failed.cpp (+1-1)
  • (modified) clang/test/SemaCXX/member-pointer.cpp (+4-13)
  • (modified) clang/test/SemaOpenACC/combined-construct-if-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/compute-construct-clause-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/data-construct-if-ast.cpp (+2-2)
  • (modified) clang/test/SemaTemplate/instantiate-member-pointers.cpp (+1-2)
  • (modified) clang/tools/libclang/CXType.cpp (+1-3)
  • (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+4-4)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index a6b00be75abf8..108717e151b57 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,7 +493,8 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NullMacrosStr(Options.get("NullMacros", "NULL")),
       IgnoredTypes(utils::options::parseStringList(Options.get(
-          "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
+          "IgnoredTypes",
+          "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
   StringRef(NullMacrosStr).split(NullMacros, ",");
 }
 
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index bc49fa856bafc..b66cc8512fad6 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,9 +178,7 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
 
     // Note: converting Derived::* to Base::* is a different kind of conversion,
     // called Pointer-to-member conversion.
-    return FromMember->getQualifier() == ToMember->getQualifier() &&
-           FromMember->getMostRecentCXXRecordDecl() ==
-               ToMember->getMostRecentCXXRecordDecl() &&
+    return FromMember->getClass() == ToMember->getClass() &&
            FromMember->getPointeeType() == ToMember->getPointeeType();
   }
 
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 602f61d9ecb41..fc54f89f4941e 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1489,7 +1489,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
         "4: targets = {a}\n"
         "5: targets = {a::b}, qualifier = 'a::'\n"
         "6: targets = {a::b::S}\n"
-        "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
         "8: targets = {y}, decl\n"},
        {R"cpp(
          void foo() {
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 97f6ea90d4705..88862f7661191 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -267,7 +267,6 @@ Improvements to Clang's diagnostics
   under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
 - Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
   ``-Wno-error=parentheses``.
-- Clang now better preserves the sugared types of pointers to member.
 - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
 - Fixed diagnostics adding a trailing ``::`` when printing some source code
   constructs, like base classes.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index af8c49e99a7ce..f9a12260a6590 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,9 +1558,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   QualType getRValueReferenceType(QualType T) const;
 
   /// Return the uniqued reference to the type for a member pointer to
-  /// the specified type in the specified nested name.
-  QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                const CXXRecordDecl *Cls) const;
+  /// the specified type in the specified class.
+  ///
+  /// The class \p Cls is a \c Type because it could be a dependent name.
+  QualType getMemberPointerType(QualType T, const Type *Cls) const;
 
   /// Return a non-unique reference to the type for a variable array of
   /// the specified element type.
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index f557555e96e59..3bc0bdff2bdd1 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,9 +393,7 @@ class ASTNodeTraverser
     Visit(T->getPointeeType());
   }
   void VisitMemberPointerType(const MemberPointerType *T) {
-    // FIXME: Provide a NestedNameSpecifier visitor.
-    Visit(T->getQualifier()->getAsType());
-    Visit(T->getMostRecentCXXRecordDecl());
+    Visit(T->getClass());
     Visit(T->getPointeeType());
   }
   void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -487,8 +485,7 @@ class ASTNodeTraverser
     }
   }
   void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-    // FIXME: Provide NestedNamespecifierLoc visitor.
-    Visit(TL.getQualifierLoc().getTypeLoc());
+    Visit(TL.getClassTInfo()->getTypeLoc());
   }
   void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
     Visit(TL.getSizeExpr());
diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 35db68971e029..50d1ba1b8f63f 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,7 @@ template<>
 struct CanProxyAdaptor<MemberPointerType>
   : public CanProxyBase<MemberPointerType> {
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
                                       getMostRecentCXXRecordDecl)
 };
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index e93d1d8eab56f..87a6c22b35ee8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,8 +1004,7 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
                   { TRY_TO(TraverseType(T->getPointeeType())); })
 
 DEF_TRAVERSE_TYPE(MemberPointerType, {
-  TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
-  TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
+  TRY_TO(TraverseType(QualType(T->getClass(), 0)));
   TRY_TO(TraverseType(T->getPointeeType()));
 })
 
@@ -1270,10 +1269,10 @@ DEF_TRAVERSE_TYPELOC(RValueReferenceType,
 // We traverse this in the type case as well, but how is it not reached through
 // the pointee type?
 DEF_TRAVERSE_TYPELOC(MemberPointerType, {
-  if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
-    TRY_TO(TraverseNestedNameSpecifierLoc(QL));
+  if (auto *TSI = TL.getClassTInfo())
+    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
   else
-    TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+    TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
   TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
 })
 
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 65756203f2073..3c942f2ed7486 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3527,16 +3527,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
   QualType PointeeType;
 
   /// The class of which the pointee is a member. Must ultimately be a
-  /// CXXRecordType, but could be a typedef or a template parameter too.
-  NestedNameSpecifier *Qualifier;
+  /// RecordType, but could be a typedef or a template parameter too.
+  const Type *Class;
 
-  MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
-                    QualType CanonicalPtr)
+  MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
       : Type(MemberPointer, CanonicalPtr,
-             (toTypeDependence(Qualifier->getDependence()) &
-              ~TypeDependence::VariablyModified) |
+             (Cls->getDependence() & ~TypeDependence::VariablyModified) |
                  Pointee->getDependence()),
-        PointeeType(Pointee), Qualifier(Qualifier) {}
+        PointeeType(Pointee), Class(Cls) {}
 
 public:
   QualType getPointeeType() const { return PointeeType; }
@@ -3553,21 +3551,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
     return !PointeeType->isFunctionProtoType();
   }
 
-  NestedNameSpecifier *getQualifier() const { return Qualifier; }
+  const Type *getClass() const { return Class; }
   CXXRecordDecl *getMostRecentCXXRecordDecl() const;
 
-  bool isSugared() const;
-  QualType desugar() const {
-    return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
-  }
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
+    Profile(ID, getPointeeType(), getClass());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
-                      const NestedNameSpecifier *Qualifier,
-                      const CXXRecordDecl *Cls);
+                      const Type *Class) {
+    ID.AddPointer(Pointee.getAsOpaquePtr());
+    ID.AddPointer(Class);
+  }
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == MemberPointer;
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 17ce09fa5da4f..a55a38335ef6a 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -139,7 +139,6 @@ class TypeLoc {
   }
 
   /// Get the pointer where source information is stored.
-  // FIXME: This should provide a type-safe interface.
   void *getOpaqueData() const {
     return Data;
   }
@@ -1356,7 +1355,7 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
 };
 
 struct MemberPointerLocInfo : public PointerLikeLocInfo {
-  void *QualifierData = nullptr;
+  TypeSourceInfo *ClassTInfo;
 };
 
 /// Wrapper for source info for member pointers.
@@ -1372,32 +1371,28 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
     setSigilLoc(Loc);
   }
 
-  NestedNameSpecifierLoc getQualifierLoc() const {
-    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
-                                  getLocalData()->QualifierData);
+  const Type *getClass() const {
+    return getTypePtr()->getClass();
   }
 
-  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
-    assert(QualifierLoc.getNestedNameSpecifier() ==
-               getTypePtr()->getQualifier() &&
-           "Inconsistent nested-name-specifier pointer");
-    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+  TypeSourceInfo *getClassTInfo() const {
+    return getLocalData()->ClassTInfo;
+  }
+
+  void setClassTInfo(TypeSourceInfo* TI) {
+    getLocalData()->ClassTInfo = TI;
   }
 
   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
     setSigilLoc(Loc);
-    if (auto *Qualifier = getTypePtr()->getQualifier()) {
-      NestedNameSpecifierLocBuilder Builder;
-      Builder.MakeTrivial(Context, Qualifier, Loc);
-      setQualifierLoc(Builder.getWithLocInContext(Context));
-    } else
-      getLocalData()->QualifierData = nullptr;
+    setClassTInfo(nullptr);
   }
 
   SourceRange getLocalSourceRange() const {
-    if (NestedNameSpecifierLoc QL = getQualifierLoc())
-      return SourceRange(QL.getBeginLoc(), getStarLoc());
-    return SourceRange(getStarLoc());
+    if (TypeSourceInfo *TI = getClassTInfo())
+      return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
+    else
+      return SourceRange(getStarLoc());
   }
 };
 
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 27f71bf5cc62f..6f1a76bd18fb5 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,15 +100,12 @@ let Class = MemberPointerType in {
   def : Property<"pointeeType", QualType> {
     let Read = [{ node->getPointeeType() }];
   }
-  def : Property<"Qualifier", NestedNameSpecifier> {
-    let Read = [{ node->getQualifier() }];
-  }
-  def : Property<"Cls", DeclRef> {
-    let Read = [{ node->getMostRecentCXXRecordDecl() }];
+  def : Property<"baseType", QualType> {
+    let Read = [{ QualType(node->getClass(), 0) }];
   }
 
   def : Creator<[{
-    return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
+    return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
   }]>;
 }
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4cb8f3d759817..1536a3b8c920a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7065,8 +7065,10 @@ def err_illegal_decl_mempointer_to_reference : Error<
   "'%0' declared as a member pointer to a reference of type %1">;
 def err_illegal_decl_mempointer_to_void : Error<
   "'%0' declared as a member pointer to void">;
-def err_illegal_decl_mempointer_in_nonclass
-    : Error<"'%0' does not point into a class">;
+def err_illegal_decl_mempointer_in_nonclass : Error<
+  "'%0' does not point into a class">;
+def err_mempointer_in_nonclass_type : Error<
+  "member pointer refers into non-class type %0">;
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_nonfunction_block_type : Error<
   "block pointer to non-function type is invalid">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e215f07e2bf0a..9724f0def743a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,12 +1348,6 @@ class Sema final : public SemaBase {
                                     unsigned DiagID, bool ForceCheck = false,
                                     bool ForceUnprivileged = false);
 
-  AccessResult CheckBaseClassAccess(
-      SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
-      const CXXBasePath &Path, unsigned DiagID,
-      llvm::function_ref<void(PartialDiagnostic &PD)> SetupPDiag,
-      bool ForceCheck = false, bool ForceUnprivileged = false);
-
   /// Checks access to all the declarations in the given result set.
   void CheckLookupAccess(const LookupResult &R);
 
@@ -14885,9 +14879,8 @@ class Sema final : public SemaBase {
   ///
   /// \returns a member pointer type, if successful, or a NULL type if there was
   /// an error.
-  QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                  CXXRecordDecl *Cls, SourceLocation Loc,
-                                  DeclarationName Entity);
+  QualType BuildMemberPointerType(QualType T, QualType Class,
+                                  SourceLocation Loc, DeclarationName Entity);
 
   /// Build a block pointer type.
   ///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index de868ac821745..68a02f3bbe1ec 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3322,8 +3322,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
   case Type::MemberPointer: {
     OS << "M";
     const auto *MPT = T->castAs<MemberPointerType>();
-    encodeTypeForFunctionPointerAuth(
-        Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
+    encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
     encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
     return;
   }
@@ -3512,8 +3511,7 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) {
         if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
             EST_None) {
           QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
-          T = getMemberPointerType(FT, MPT->getQualifier(),
-                                   MPT->getMostRecentCXXRecordDecl());
+          T = getMemberPointerType(FT, MPT->getClass());
         }
       }
     std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4027,50 +4025,32 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
   return QualType(New, 0);
 }
 
-QualType ASTContext::getMemberPointerType(QualType T,
-                                          NestedNameSpecifier *Qualifier,
-                                          const CXXRecordDecl *Cls) const {
-  if (!Qualifier) {
-    assert(Cls && "At least one of Qualifier or Cls must be provided");
-    Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
-                                            /*Template=*/false,
-                                            getTypeDeclType(Cls).getTypePtr());
-  } else if (!Cls) {
-    Cls = Qualifier->getAsRecordDecl();
-  }
+/// getMemberPointerType - Return the uniqued reference to the type for a
+/// member pointer to the specified type, in the specified class.
+QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
   // Unique pointers, to guarantee there is only one pointer of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  MemberPointerType::Profile(ID, T, Qualifier, Cls);
+  MemberPointerType::Profile(ID, T, Cls);
 
   void *InsertPos = nullptr;
   if (MemberPointerType *PT =
       MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(PT, 0);
 
-  NestedNameSpecifier *CanonicalQualifier = [&] {
-    if (!Cls)
-      return getCanonicalNestedNameSpecifier(Qualifier);
-    NestedNameSpecifier *R = NestedNameSpecifier::Create(
-        *this, /*Prefix=*/nullptr, /*Template=*/false,
-        Cls->getCanonicalDecl()->getTypeForDecl());
-    assert(R == getCanonicalNestedNameSpecifier(R));
-    return R;
-  }();
   // If the pointee or class type isn't canonical, this won't be a canonical
   // type either, so fill in the canonical type field.
   QualType Canonical;
-  if (!T.isCanonical() || Qualifier != CanonicalQualifier) {
-    Canonical =
-        getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls);
-    assert(!cast<MemberPointerType>(Canonical)->isSugared());
+  if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
+    Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
+
     // Get the new insert position for the node we care about.
-    [[maybe_unused]] MemberPointerType *NewIP =
-        MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(!NewIP && "Shouldn't be in the map!");
+    MemberPointerType *NewIP =
+      MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
   }
   auto *New = new (*this, alignof(MemberPointerType))
-      MemberPointerType(T, Qualifier, Canonical);
+      MemberPointerType(T, Cls, Canonical);
   Types.push_back(New);
   MemberPointerTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
@@ -6832,16 +6812,11 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
     return true;
   }
 
-  if (const auto *T1MPType = T1->getAs<MemberPointerType>(),
-      *T2MPType = T2->getAs<MemberPointerType>();
-      T1MPType && T2MPType) {
-    if (auto *RD1 = T1MPType->getMostRecentCXXRecordDecl(),
-        *RD2 = T2MPType->getMostRecentCXXRecordDecl();
-        RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
-      return false;
-    if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
-        getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
-      return false;
+  const auto *T1MPType = T1->getAs<MemberPointerType>();
+  const auto *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType &&
+      hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+                             QualType(T2MPType->getClass(), 0))) {
     T1 = T1MPType->getPointeeType();
     T2 = T2MPType->getPointeeType();
     return true;
@@ -13882,12 +13857,11 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
   case Type::MemberPointer: {
     const auto *PX = cast<MemberPointerType>(X),
                *PY = cast<MemberPointerType>(Y);
-    assert(declaresSameEntity(PX->getMostRecentCXXRecordDecl(),
-                              PY->getMostRecentCXXRecordDecl()));
     return Ctx.getMemberPointerType(
         getCommonPointeeType(Ctx, PX, PY),
-        getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true),
-        PX->getMostRecentCXXRecordDec...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 20, 2025

@llvm/pr-subscribers-clang-tidy

Author: Matheus Izvekov (mizvekov)

Changes

Reverts llvm/llvm-project#130537

This missed updating lldb, which we didn't notice due to lack of pre-commit CI.


Patch is 141.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132215.diff

69 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp (+2-1)
  • (modified) clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp (+1-3)
  • (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+1-1)
  • (modified) clang/docs/ReleaseNotes.rst (-1)
  • (modified) clang/include/clang/AST/ASTContext.h (+4-3)
  • (modified) clang/include/clang/AST/ASTNodeTraverser.h (+2-5)
  • (modified) clang/include/clang/AST/CanonicalType.h (+1-1)
  • (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4-5)
  • (modified) clang/include/clang/AST/Type.h (+13-15)
  • (modified) clang/include/clang/AST/TypeLoc.h (+14-19)
  • (modified) clang/include/clang/AST/TypeProperties.td (+3-6)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4-2)
  • (modified) clang/include/clang/Sema/Sema.h (+2-9)
  • (modified) clang/lib/AST/ASTContext.cpp (+21-47)
  • (modified) clang/lib/AST/ASTImporter.cpp (+5-9)
  • (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+2-6)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+1-10)
  • (modified) clang/lib/AST/NestedNameSpecifier.cpp (-1)
  • (modified) clang/lib/AST/ODRHash.cpp (+1-1)
  • (modified) clang/lib/AST/QualTypeNames.cpp (+3-4)
  • (modified) clang/lib/AST/Type.cpp (+4-30)
  • (modified) clang/lib/AST/TypePrinter.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CGCXXABI.cpp (+1-1)
  • (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CGVTables.cpp (+3-2)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+5-5)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+3-4)
  • (modified) clang/lib/Sema/SemaAccess.cpp (+8-18)
  • (modified) clang/lib/Sema/SemaCast.cpp (+2-2)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+6-4)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+1-3)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+3-2)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+27-60)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+2-6)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+5-16)
  • (modified) clang/lib/Sema/SemaType.cpp (+100-22)
  • (modified) clang/lib/Sema/TreeTransform.h (+30-29)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+1-1)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+1-1)
  • (modified) clang/lib/Serialization/TemplateArgumentHasher.cpp (+1-3)
  • (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+1-3)
  • (modified) clang/test/AST/ast-dump-templates.cpp (-238)
  • (modified) clang/test/AST/ast-dump-types-json.cpp (+44-338)
  • (modified) clang/test/AST/attr-print-emit.cpp (+1-1)
  • (modified) clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (+5-5)
  • (modified) clang/test/CXX/class.access/p6.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg0xx.cpp (+6-6)
  • (modified) clang/test/CXX/drs/cwg13xx.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg26xx.cpp (+3-3)
  • (modified) clang/test/CXX/drs/cwg2xx.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg4xx.cpp (+1-1)
  • (modified) clang/test/CXX/drs/cwg7xx.cpp (+2-1)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (+1-1)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp (+3-3)
  • (modified) clang/test/Index/print-type.cpp (+1-1)
  • (modified) clang/test/SemaCXX/addr-of-overloaded-function.cpp (+13-13)
  • (modified) clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp (+2-2)
  • (modified) clang/test/SemaCXX/calling-conv-compat.cpp (+21-21)
  • (modified) clang/test/SemaCXX/err_init_conversion_failed.cpp (+1-1)
  • (modified) clang/test/SemaCXX/member-pointer.cpp (+4-13)
  • (modified) clang/test/SemaOpenACC/combined-construct-if-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/compute-construct-clause-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/data-construct-if-ast.cpp (+2-2)
  • (modified) clang/test/SemaTemplate/instantiate-member-pointers.cpp (+1-2)
  • (modified) clang/tools/libclang/CXType.cpp (+1-3)
  • (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+4-4)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index a6b00be75abf8..108717e151b57 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,7 +493,8 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NullMacrosStr(Options.get("NullMacros", "NULL")),
       IgnoredTypes(utils::options::parseStringList(Options.get(
-          "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
+          "IgnoredTypes",
+          "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
   StringRef(NullMacrosStr).split(NullMacros, ",");
 }
 
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index bc49fa856bafc..b66cc8512fad6 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,9 +178,7 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
 
     // Note: converting Derived::* to Base::* is a different kind of conversion,
     // called Pointer-to-member conversion.
-    return FromMember->getQualifier() == ToMember->getQualifier() &&
-           FromMember->getMostRecentCXXRecordDecl() ==
-               ToMember->getMostRecentCXXRecordDecl() &&
+    return FromMember->getClass() == ToMember->getClass() &&
            FromMember->getPointeeType() == ToMember->getPointeeType();
   }
 
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 602f61d9ecb41..fc54f89f4941e 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1489,7 +1489,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
         "4: targets = {a}\n"
         "5: targets = {a::b}, qualifier = 'a::'\n"
         "6: targets = {a::b::S}\n"
-        "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
         "8: targets = {y}, decl\n"},
        {R"cpp(
          void foo() {
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 97f6ea90d4705..88862f7661191 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -267,7 +267,6 @@ Improvements to Clang's diagnostics
   under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
 - Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
   ``-Wno-error=parentheses``.
-- Clang now better preserves the sugared types of pointers to member.
 - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
 - Fixed diagnostics adding a trailing ``::`` when printing some source code
   constructs, like base classes.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index af8c49e99a7ce..f9a12260a6590 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,9 +1558,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   QualType getRValueReferenceType(QualType T) const;
 
   /// Return the uniqued reference to the type for a member pointer to
-  /// the specified type in the specified nested name.
-  QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                const CXXRecordDecl *Cls) const;
+  /// the specified type in the specified class.
+  ///
+  /// The class \p Cls is a \c Type because it could be a dependent name.
+  QualType getMemberPointerType(QualType T, const Type *Cls) const;
 
   /// Return a non-unique reference to the type for a variable array of
   /// the specified element type.
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index f557555e96e59..3bc0bdff2bdd1 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,9 +393,7 @@ class ASTNodeTraverser
     Visit(T->getPointeeType());
   }
   void VisitMemberPointerType(const MemberPointerType *T) {
-    // FIXME: Provide a NestedNameSpecifier visitor.
-    Visit(T->getQualifier()->getAsType());
-    Visit(T->getMostRecentCXXRecordDecl());
+    Visit(T->getClass());
     Visit(T->getPointeeType());
   }
   void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -487,8 +485,7 @@ class ASTNodeTraverser
     }
   }
   void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-    // FIXME: Provide NestedNamespecifierLoc visitor.
-    Visit(TL.getQualifierLoc().getTypeLoc());
+    Visit(TL.getClassTInfo()->getTypeLoc());
   }
   void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
     Visit(TL.getSizeExpr());
diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 35db68971e029..50d1ba1b8f63f 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,7 @@ template<>
 struct CanProxyAdaptor<MemberPointerType>
   : public CanProxyBase<MemberPointerType> {
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
                                       getMostRecentCXXRecordDecl)
 };
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index e93d1d8eab56f..87a6c22b35ee8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,8 +1004,7 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
                   { TRY_TO(TraverseType(T->getPointeeType())); })
 
 DEF_TRAVERSE_TYPE(MemberPointerType, {
-  TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
-  TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
+  TRY_TO(TraverseType(QualType(T->getClass(), 0)));
   TRY_TO(TraverseType(T->getPointeeType()));
 })
 
@@ -1270,10 +1269,10 @@ DEF_TRAVERSE_TYPELOC(RValueReferenceType,
 // We traverse this in the type case as well, but how is it not reached through
 // the pointee type?
 DEF_TRAVERSE_TYPELOC(MemberPointerType, {
-  if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
-    TRY_TO(TraverseNestedNameSpecifierLoc(QL));
+  if (auto *TSI = TL.getClassTInfo())
+    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
   else
-    TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+    TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
   TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
 })
 
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 65756203f2073..3c942f2ed7486 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3527,16 +3527,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
   QualType PointeeType;
 
   /// The class of which the pointee is a member. Must ultimately be a
-  /// CXXRecordType, but could be a typedef or a template parameter too.
-  NestedNameSpecifier *Qualifier;
+  /// RecordType, but could be a typedef or a template parameter too.
+  const Type *Class;
 
-  MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
-                    QualType CanonicalPtr)
+  MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
       : Type(MemberPointer, CanonicalPtr,
-             (toTypeDependence(Qualifier->getDependence()) &
-              ~TypeDependence::VariablyModified) |
+             (Cls->getDependence() & ~TypeDependence::VariablyModified) |
                  Pointee->getDependence()),
-        PointeeType(Pointee), Qualifier(Qualifier) {}
+        PointeeType(Pointee), Class(Cls) {}
 
 public:
   QualType getPointeeType() const { return PointeeType; }
@@ -3553,21 +3551,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
     return !PointeeType->isFunctionProtoType();
   }
 
-  NestedNameSpecifier *getQualifier() const { return Qualifier; }
+  const Type *getClass() const { return Class; }
   CXXRecordDecl *getMostRecentCXXRecordDecl() const;
 
-  bool isSugared() const;
-  QualType desugar() const {
-    return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
-  }
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
+    Profile(ID, getPointeeType(), getClass());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
-                      const NestedNameSpecifier *Qualifier,
-                      const CXXRecordDecl *Cls);
+                      const Type *Class) {
+    ID.AddPointer(Pointee.getAsOpaquePtr());
+    ID.AddPointer(Class);
+  }
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == MemberPointer;
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 17ce09fa5da4f..a55a38335ef6a 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -139,7 +139,6 @@ class TypeLoc {
   }
 
   /// Get the pointer where source information is stored.
-  // FIXME: This should provide a type-safe interface.
   void *getOpaqueData() const {
     return Data;
   }
@@ -1356,7 +1355,7 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
 };
 
 struct MemberPointerLocInfo : public PointerLikeLocInfo {
-  void *QualifierData = nullptr;
+  TypeSourceInfo *ClassTInfo;
 };
 
 /// Wrapper for source info for member pointers.
@@ -1372,32 +1371,28 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
     setSigilLoc(Loc);
   }
 
-  NestedNameSpecifierLoc getQualifierLoc() const {
-    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
-                                  getLocalData()->QualifierData);
+  const Type *getClass() const {
+    return getTypePtr()->getClass();
   }
 
-  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
-    assert(QualifierLoc.getNestedNameSpecifier() ==
-               getTypePtr()->getQualifier() &&
-           "Inconsistent nested-name-specifier pointer");
-    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+  TypeSourceInfo *getClassTInfo() const {
+    return getLocalData()->ClassTInfo;
+  }
+
+  void setClassTInfo(TypeSourceInfo* TI) {
+    getLocalData()->ClassTInfo = TI;
   }
 
   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
     setSigilLoc(Loc);
-    if (auto *Qualifier = getTypePtr()->getQualifier()) {
-      NestedNameSpecifierLocBuilder Builder;
-      Builder.MakeTrivial(Context, Qualifier, Loc);
-      setQualifierLoc(Builder.getWithLocInContext(Context));
-    } else
-      getLocalData()->QualifierData = nullptr;
+    setClassTInfo(nullptr);
   }
 
   SourceRange getLocalSourceRange() const {
-    if (NestedNameSpecifierLoc QL = getQualifierLoc())
-      return SourceRange(QL.getBeginLoc(), getStarLoc());
-    return SourceRange(getStarLoc());
+    if (TypeSourceInfo *TI = getClassTInfo())
+      return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
+    else
+      return SourceRange(getStarLoc());
   }
 };
 
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 27f71bf5cc62f..6f1a76bd18fb5 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,15 +100,12 @@ let Class = MemberPointerType in {
   def : Property<"pointeeType", QualType> {
     let Read = [{ node->getPointeeType() }];
   }
-  def : Property<"Qualifier", NestedNameSpecifier> {
-    let Read = [{ node->getQualifier() }];
-  }
-  def : Property<"Cls", DeclRef> {
-    let Read = [{ node->getMostRecentCXXRecordDecl() }];
+  def : Property<"baseType", QualType> {
+    let Read = [{ QualType(node->getClass(), 0) }];
   }
 
   def : Creator<[{
-    return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
+    return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
   }]>;
 }
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4cb8f3d759817..1536a3b8c920a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7065,8 +7065,10 @@ def err_illegal_decl_mempointer_to_reference : Error<
   "'%0' declared as a member pointer to a reference of type %1">;
 def err_illegal_decl_mempointer_to_void : Error<
   "'%0' declared as a member pointer to void">;
-def err_illegal_decl_mempointer_in_nonclass
-    : Error<"'%0' does not point into a class">;
+def err_illegal_decl_mempointer_in_nonclass : Error<
+  "'%0' does not point into a class">;
+def err_mempointer_in_nonclass_type : Error<
+  "member pointer refers into non-class type %0">;
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_nonfunction_block_type : Error<
   "block pointer to non-function type is invalid">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e215f07e2bf0a..9724f0def743a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,12 +1348,6 @@ class Sema final : public SemaBase {
                                     unsigned DiagID, bool ForceCheck = false,
                                     bool ForceUnprivileged = false);
 
-  AccessResult CheckBaseClassAccess(
-      SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
-      const CXXBasePath &Path, unsigned DiagID,
-      llvm::function_ref<void(PartialDiagnostic &PD)> SetupPDiag,
-      bool ForceCheck = false, bool ForceUnprivileged = false);
-
   /// Checks access to all the declarations in the given result set.
   void CheckLookupAccess(const LookupResult &R);
 
@@ -14885,9 +14879,8 @@ class Sema final : public SemaBase {
   ///
   /// \returns a member pointer type, if successful, or a NULL type if there was
   /// an error.
-  QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                  CXXRecordDecl *Cls, SourceLocation Loc,
-                                  DeclarationName Entity);
+  QualType BuildMemberPointerType(QualType T, QualType Class,
+                                  SourceLocation Loc, DeclarationName Entity);
 
   /// Build a block pointer type.
   ///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index de868ac821745..68a02f3bbe1ec 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3322,8 +3322,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
   case Type::MemberPointer: {
     OS << "M";
     const auto *MPT = T->castAs<MemberPointerType>();
-    encodeTypeForFunctionPointerAuth(
-        Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
+    encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
     encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
     return;
   }
@@ -3512,8 +3511,7 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) {
         if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
             EST_None) {
           QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
-          T = getMemberPointerType(FT, MPT->getQualifier(),
-                                   MPT->getMostRecentCXXRecordDecl());
+          T = getMemberPointerType(FT, MPT->getClass());
         }
       }
     std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4027,50 +4025,32 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
   return QualType(New, 0);
 }
 
-QualType ASTContext::getMemberPointerType(QualType T,
-                                          NestedNameSpecifier *Qualifier,
-                                          const CXXRecordDecl *Cls) const {
-  if (!Qualifier) {
-    assert(Cls && "At least one of Qualifier or Cls must be provided");
-    Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
-                                            /*Template=*/false,
-                                            getTypeDeclType(Cls).getTypePtr());
-  } else if (!Cls) {
-    Cls = Qualifier->getAsRecordDecl();
-  }
+/// getMemberPointerType - Return the uniqued reference to the type for a
+/// member pointer to the specified type, in the specified class.
+QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
   // Unique pointers, to guarantee there is only one pointer of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  MemberPointerType::Profile(ID, T, Qualifier, Cls);
+  MemberPointerType::Profile(ID, T, Cls);
 
   void *InsertPos = nullptr;
   if (MemberPointerType *PT =
       MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(PT, 0);
 
-  NestedNameSpecifier *CanonicalQualifier = [&] {
-    if (!Cls)
-      return getCanonicalNestedNameSpecifier(Qualifier);
-    NestedNameSpecifier *R = NestedNameSpecifier::Create(
-        *this, /*Prefix=*/nullptr, /*Template=*/false,
-        Cls->getCanonicalDecl()->getTypeForDecl());
-    assert(R == getCanonicalNestedNameSpecifier(R));
-    return R;
-  }();
   // If the pointee or class type isn't canonical, this won't be a canonical
   // type either, so fill in the canonical type field.
   QualType Canonical;
-  if (!T.isCanonical() || Qualifier != CanonicalQualifier) {
-    Canonical =
-        getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls);
-    assert(!cast<MemberPointerType>(Canonical)->isSugared());
+  if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
+    Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
+
     // Get the new insert position for the node we care about.
-    [[maybe_unused]] MemberPointerType *NewIP =
-        MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(!NewIP && "Shouldn't be in the map!");
+    MemberPointerType *NewIP =
+      MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
   }
   auto *New = new (*this, alignof(MemberPointerType))
-      MemberPointerType(T, Qualifier, Canonical);
+      MemberPointerType(T, Cls, Canonical);
   Types.push_back(New);
   MemberPointerTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
@@ -6832,16 +6812,11 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
     return true;
   }
 
-  if (const auto *T1MPType = T1->getAs<MemberPointerType>(),
-      *T2MPType = T2->getAs<MemberPointerType>();
-      T1MPType && T2MPType) {
-    if (auto *RD1 = T1MPType->getMostRecentCXXRecordDecl(),
-        *RD2 = T2MPType->getMostRecentCXXRecordDecl();
-        RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
-      return false;
-    if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
-        getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
-      return false;
+  const auto *T1MPType = T1->getAs<MemberPointerType>();
+  const auto *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType &&
+      hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+                             QualType(T2MPType->getClass(), 0))) {
     T1 = T1MPType->getPointeeType();
     T2 = T2MPType->getPointeeType();
     return true;
@@ -13882,12 +13857,11 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
   case Type::MemberPointer: {
     const auto *PX = cast<MemberPointerType>(X),
                *PY = cast<MemberPointerType>(Y);
-    assert(declaresSameEntity(PX->getMostRecentCXXRecordDecl(),
-                              PY->getMostRecentCXXRecordDecl()));
     return Ctx.getMemberPointerType(
         getCommonPointeeType(Ctx, PX, PY),
-        getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true),
-        PX->getMostRecentCXXRecordDec...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 20, 2025

@llvm/pr-subscribers-clangd

Author: Matheus Izvekov (mizvekov)

Changes

Reverts llvm/llvm-project#130537

This missed updating lldb, which we didn't notice due to lack of pre-commit CI.


Patch is 141.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132215.diff

69 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp (+2-1)
  • (modified) clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp (+1-3)
  • (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+1-1)
  • (modified) clang/docs/ReleaseNotes.rst (-1)
  • (modified) clang/include/clang/AST/ASTContext.h (+4-3)
  • (modified) clang/include/clang/AST/ASTNodeTraverser.h (+2-5)
  • (modified) clang/include/clang/AST/CanonicalType.h (+1-1)
  • (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4-5)
  • (modified) clang/include/clang/AST/Type.h (+13-15)
  • (modified) clang/include/clang/AST/TypeLoc.h (+14-19)
  • (modified) clang/include/clang/AST/TypeProperties.td (+3-6)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4-2)
  • (modified) clang/include/clang/Sema/Sema.h (+2-9)
  • (modified) clang/lib/AST/ASTContext.cpp (+21-47)
  • (modified) clang/lib/AST/ASTImporter.cpp (+5-9)
  • (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+2-6)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+1-10)
  • (modified) clang/lib/AST/NestedNameSpecifier.cpp (-1)
  • (modified) clang/lib/AST/ODRHash.cpp (+1-1)
  • (modified) clang/lib/AST/QualTypeNames.cpp (+3-4)
  • (modified) clang/lib/AST/Type.cpp (+4-30)
  • (modified) clang/lib/AST/TypePrinter.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CGCXXABI.cpp (+1-1)
  • (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+2-2)
  • (modified) clang/lib/CodeGen/CGVTables.cpp (+3-2)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+5-5)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+3-4)
  • (modified) clang/lib/Sema/SemaAccess.cpp (+8-18)
  • (modified) clang/lib/Sema/SemaCast.cpp (+2-2)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+6-4)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+1-3)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+3-2)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+27-60)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+2-6)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+5-16)
  • (modified) clang/lib/Sema/SemaType.cpp (+100-22)
  • (modified) clang/lib/Sema/TreeTransform.h (+30-29)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+1-1)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+1-1)
  • (modified) clang/lib/Serialization/TemplateArgumentHasher.cpp (+1-3)
  • (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+1-3)
  • (modified) clang/test/AST/ast-dump-templates.cpp (-238)
  • (modified) clang/test/AST/ast-dump-types-json.cpp (+44-338)
  • (modified) clang/test/AST/attr-print-emit.cpp (+1-1)
  • (modified) clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (+5-5)
  • (modified) clang/test/CXX/class.access/p6.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg0xx.cpp (+6-6)
  • (modified) clang/test/CXX/drs/cwg13xx.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg26xx.cpp (+3-3)
  • (modified) clang/test/CXX/drs/cwg2xx.cpp (+2-2)
  • (modified) clang/test/CXX/drs/cwg4xx.cpp (+1-1)
  • (modified) clang/test/CXX/drs/cwg7xx.cpp (+2-1)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (+1-1)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp (+3-3)
  • (modified) clang/test/Index/print-type.cpp (+1-1)
  • (modified) clang/test/SemaCXX/addr-of-overloaded-function.cpp (+13-13)
  • (modified) clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp (+2-2)
  • (modified) clang/test/SemaCXX/calling-conv-compat.cpp (+21-21)
  • (modified) clang/test/SemaCXX/err_init_conversion_failed.cpp (+1-1)
  • (modified) clang/test/SemaCXX/member-pointer.cpp (+4-13)
  • (modified) clang/test/SemaOpenACC/combined-construct-if-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/compute-construct-clause-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp (+2-2)
  • (modified) clang/test/SemaOpenACC/data-construct-if-ast.cpp (+2-2)
  • (modified) clang/test/SemaTemplate/instantiate-member-pointers.cpp (+1-2)
  • (modified) clang/tools/libclang/CXType.cpp (+1-3)
  • (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+4-4)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index a6b00be75abf8..108717e151b57 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,7 +493,8 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NullMacrosStr(Options.get("NullMacros", "NULL")),
       IgnoredTypes(utils::options::parseStringList(Options.get(
-          "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
+          "IgnoredTypes",
+          "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
   StringRef(NullMacrosStr).split(NullMacros, ",");
 }
 
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index bc49fa856bafc..b66cc8512fad6 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,9 +178,7 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
 
     // Note: converting Derived::* to Base::* is a different kind of conversion,
     // called Pointer-to-member conversion.
-    return FromMember->getQualifier() == ToMember->getQualifier() &&
-           FromMember->getMostRecentCXXRecordDecl() ==
-               ToMember->getMostRecentCXXRecordDecl() &&
+    return FromMember->getClass() == ToMember->getClass() &&
            FromMember->getPointeeType() == ToMember->getPointeeType();
   }
 
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 602f61d9ecb41..fc54f89f4941e 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1489,7 +1489,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
         "4: targets = {a}\n"
         "5: targets = {a::b}, qualifier = 'a::'\n"
         "6: targets = {a::b::S}\n"
-        "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
         "8: targets = {y}, decl\n"},
        {R"cpp(
          void foo() {
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 97f6ea90d4705..88862f7661191 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -267,7 +267,6 @@ Improvements to Clang's diagnostics
   under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
 - Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
   ``-Wno-error=parentheses``.
-- Clang now better preserves the sugared types of pointers to member.
 - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
 - Fixed diagnostics adding a trailing ``::`` when printing some source code
   constructs, like base classes.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index af8c49e99a7ce..f9a12260a6590 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,9 +1558,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   QualType getRValueReferenceType(QualType T) const;
 
   /// Return the uniqued reference to the type for a member pointer to
-  /// the specified type in the specified nested name.
-  QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                const CXXRecordDecl *Cls) const;
+  /// the specified type in the specified class.
+  ///
+  /// The class \p Cls is a \c Type because it could be a dependent name.
+  QualType getMemberPointerType(QualType T, const Type *Cls) const;
 
   /// Return a non-unique reference to the type for a variable array of
   /// the specified element type.
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index f557555e96e59..3bc0bdff2bdd1 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,9 +393,7 @@ class ASTNodeTraverser
     Visit(T->getPointeeType());
   }
   void VisitMemberPointerType(const MemberPointerType *T) {
-    // FIXME: Provide a NestedNameSpecifier visitor.
-    Visit(T->getQualifier()->getAsType());
-    Visit(T->getMostRecentCXXRecordDecl());
+    Visit(T->getClass());
     Visit(T->getPointeeType());
   }
   void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -487,8 +485,7 @@ class ASTNodeTraverser
     }
   }
   void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-    // FIXME: Provide NestedNamespecifierLoc visitor.
-    Visit(TL.getQualifierLoc().getTypeLoc());
+    Visit(TL.getClassTInfo()->getTypeLoc());
   }
   void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
     Visit(TL.getSizeExpr());
diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 35db68971e029..50d1ba1b8f63f 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,7 @@ template<>
 struct CanProxyAdaptor<MemberPointerType>
   : public CanProxyBase<MemberPointerType> {
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
                                       getMostRecentCXXRecordDecl)
 };
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index e93d1d8eab56f..87a6c22b35ee8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,8 +1004,7 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
                   { TRY_TO(TraverseType(T->getPointeeType())); })
 
 DEF_TRAVERSE_TYPE(MemberPointerType, {
-  TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
-  TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
+  TRY_TO(TraverseType(QualType(T->getClass(), 0)));
   TRY_TO(TraverseType(T->getPointeeType()));
 })
 
@@ -1270,10 +1269,10 @@ DEF_TRAVERSE_TYPELOC(RValueReferenceType,
 // We traverse this in the type case as well, but how is it not reached through
 // the pointee type?
 DEF_TRAVERSE_TYPELOC(MemberPointerType, {
-  if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
-    TRY_TO(TraverseNestedNameSpecifierLoc(QL));
+  if (auto *TSI = TL.getClassTInfo())
+    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
   else
-    TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+    TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
   TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
 })
 
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 65756203f2073..3c942f2ed7486 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3527,16 +3527,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
   QualType PointeeType;
 
   /// The class of which the pointee is a member. Must ultimately be a
-  /// CXXRecordType, but could be a typedef or a template parameter too.
-  NestedNameSpecifier *Qualifier;
+  /// RecordType, but could be a typedef or a template parameter too.
+  const Type *Class;
 
-  MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
-                    QualType CanonicalPtr)
+  MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
       : Type(MemberPointer, CanonicalPtr,
-             (toTypeDependence(Qualifier->getDependence()) &
-              ~TypeDependence::VariablyModified) |
+             (Cls->getDependence() & ~TypeDependence::VariablyModified) |
                  Pointee->getDependence()),
-        PointeeType(Pointee), Qualifier(Qualifier) {}
+        PointeeType(Pointee), Class(Cls) {}
 
 public:
   QualType getPointeeType() const { return PointeeType; }
@@ -3553,21 +3551,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
     return !PointeeType->isFunctionProtoType();
   }
 
-  NestedNameSpecifier *getQualifier() const { return Qualifier; }
+  const Type *getClass() const { return Class; }
   CXXRecordDecl *getMostRecentCXXRecordDecl() const;
 
-  bool isSugared() const;
-  QualType desugar() const {
-    return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
-  }
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
+    Profile(ID, getPointeeType(), getClass());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
-                      const NestedNameSpecifier *Qualifier,
-                      const CXXRecordDecl *Cls);
+                      const Type *Class) {
+    ID.AddPointer(Pointee.getAsOpaquePtr());
+    ID.AddPointer(Class);
+  }
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == MemberPointer;
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 17ce09fa5da4f..a55a38335ef6a 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -139,7 +139,6 @@ class TypeLoc {
   }
 
   /// Get the pointer where source information is stored.
-  // FIXME: This should provide a type-safe interface.
   void *getOpaqueData() const {
     return Data;
   }
@@ -1356,7 +1355,7 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
 };
 
 struct MemberPointerLocInfo : public PointerLikeLocInfo {
-  void *QualifierData = nullptr;
+  TypeSourceInfo *ClassTInfo;
 };
 
 /// Wrapper for source info for member pointers.
@@ -1372,32 +1371,28 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
     setSigilLoc(Loc);
   }
 
-  NestedNameSpecifierLoc getQualifierLoc() const {
-    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
-                                  getLocalData()->QualifierData);
+  const Type *getClass() const {
+    return getTypePtr()->getClass();
   }
 
-  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
-    assert(QualifierLoc.getNestedNameSpecifier() ==
-               getTypePtr()->getQualifier() &&
-           "Inconsistent nested-name-specifier pointer");
-    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+  TypeSourceInfo *getClassTInfo() const {
+    return getLocalData()->ClassTInfo;
+  }
+
+  void setClassTInfo(TypeSourceInfo* TI) {
+    getLocalData()->ClassTInfo = TI;
   }
 
   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
     setSigilLoc(Loc);
-    if (auto *Qualifier = getTypePtr()->getQualifier()) {
-      NestedNameSpecifierLocBuilder Builder;
-      Builder.MakeTrivial(Context, Qualifier, Loc);
-      setQualifierLoc(Builder.getWithLocInContext(Context));
-    } else
-      getLocalData()->QualifierData = nullptr;
+    setClassTInfo(nullptr);
   }
 
   SourceRange getLocalSourceRange() const {
-    if (NestedNameSpecifierLoc QL = getQualifierLoc())
-      return SourceRange(QL.getBeginLoc(), getStarLoc());
-    return SourceRange(getStarLoc());
+    if (TypeSourceInfo *TI = getClassTInfo())
+      return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
+    else
+      return SourceRange(getStarLoc());
   }
 };
 
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 27f71bf5cc62f..6f1a76bd18fb5 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,15 +100,12 @@ let Class = MemberPointerType in {
   def : Property<"pointeeType", QualType> {
     let Read = [{ node->getPointeeType() }];
   }
-  def : Property<"Qualifier", NestedNameSpecifier> {
-    let Read = [{ node->getQualifier() }];
-  }
-  def : Property<"Cls", DeclRef> {
-    let Read = [{ node->getMostRecentCXXRecordDecl() }];
+  def : Property<"baseType", QualType> {
+    let Read = [{ QualType(node->getClass(), 0) }];
   }
 
   def : Creator<[{
-    return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
+    return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
   }]>;
 }
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4cb8f3d759817..1536a3b8c920a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7065,8 +7065,10 @@ def err_illegal_decl_mempointer_to_reference : Error<
   "'%0' declared as a member pointer to a reference of type %1">;
 def err_illegal_decl_mempointer_to_void : Error<
   "'%0' declared as a member pointer to void">;
-def err_illegal_decl_mempointer_in_nonclass
-    : Error<"'%0' does not point into a class">;
+def err_illegal_decl_mempointer_in_nonclass : Error<
+  "'%0' does not point into a class">;
+def err_mempointer_in_nonclass_type : Error<
+  "member pointer refers into non-class type %0">;
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_nonfunction_block_type : Error<
   "block pointer to non-function type is invalid">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e215f07e2bf0a..9724f0def743a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,12 +1348,6 @@ class Sema final : public SemaBase {
                                     unsigned DiagID, bool ForceCheck = false,
                                     bool ForceUnprivileged = false);
 
-  AccessResult CheckBaseClassAccess(
-      SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
-      const CXXBasePath &Path, unsigned DiagID,
-      llvm::function_ref<void(PartialDiagnostic &PD)> SetupPDiag,
-      bool ForceCheck = false, bool ForceUnprivileged = false);
-
   /// Checks access to all the declarations in the given result set.
   void CheckLookupAccess(const LookupResult &R);
 
@@ -14885,9 +14879,8 @@ class Sema final : public SemaBase {
   ///
   /// \returns a member pointer type, if successful, or a NULL type if there was
   /// an error.
-  QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                  CXXRecordDecl *Cls, SourceLocation Loc,
-                                  DeclarationName Entity);
+  QualType BuildMemberPointerType(QualType T, QualType Class,
+                                  SourceLocation Loc, DeclarationName Entity);
 
   /// Build a block pointer type.
   ///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index de868ac821745..68a02f3bbe1ec 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3322,8 +3322,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
   case Type::MemberPointer: {
     OS << "M";
     const auto *MPT = T->castAs<MemberPointerType>();
-    encodeTypeForFunctionPointerAuth(
-        Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
+    encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
     encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
     return;
   }
@@ -3512,8 +3511,7 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) {
         if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
             EST_None) {
           QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
-          T = getMemberPointerType(FT, MPT->getQualifier(),
-                                   MPT->getMostRecentCXXRecordDecl());
+          T = getMemberPointerType(FT, MPT->getClass());
         }
       }
     std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4027,50 +4025,32 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
   return QualType(New, 0);
 }
 
-QualType ASTContext::getMemberPointerType(QualType T,
-                                          NestedNameSpecifier *Qualifier,
-                                          const CXXRecordDecl *Cls) const {
-  if (!Qualifier) {
-    assert(Cls && "At least one of Qualifier or Cls must be provided");
-    Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
-                                            /*Template=*/false,
-                                            getTypeDeclType(Cls).getTypePtr());
-  } else if (!Cls) {
-    Cls = Qualifier->getAsRecordDecl();
-  }
+/// getMemberPointerType - Return the uniqued reference to the type for a
+/// member pointer to the specified type, in the specified class.
+QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
   // Unique pointers, to guarantee there is only one pointer of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  MemberPointerType::Profile(ID, T, Qualifier, Cls);
+  MemberPointerType::Profile(ID, T, Cls);
 
   void *InsertPos = nullptr;
   if (MemberPointerType *PT =
       MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(PT, 0);
 
-  NestedNameSpecifier *CanonicalQualifier = [&] {
-    if (!Cls)
-      return getCanonicalNestedNameSpecifier(Qualifier);
-    NestedNameSpecifier *R = NestedNameSpecifier::Create(
-        *this, /*Prefix=*/nullptr, /*Template=*/false,
-        Cls->getCanonicalDecl()->getTypeForDecl());
-    assert(R == getCanonicalNestedNameSpecifier(R));
-    return R;
-  }();
   // If the pointee or class type isn't canonical, this won't be a canonical
   // type either, so fill in the canonical type field.
   QualType Canonical;
-  if (!T.isCanonical() || Qualifier != CanonicalQualifier) {
-    Canonical =
-        getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls);
-    assert(!cast<MemberPointerType>(Canonical)->isSugared());
+  if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
+    Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
+
     // Get the new insert position for the node we care about.
-    [[maybe_unused]] MemberPointerType *NewIP =
-        MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(!NewIP && "Shouldn't be in the map!");
+    MemberPointerType *NewIP =
+      MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
   }
   auto *New = new (*this, alignof(MemberPointerType))
-      MemberPointerType(T, Qualifier, Canonical);
+      MemberPointerType(T, Cls, Canonical);
   Types.push_back(New);
   MemberPointerTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
@@ -6832,16 +6812,11 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
     return true;
   }
 
-  if (const auto *T1MPType = T1->getAs<MemberPointerType>(),
-      *T2MPType = T2->getAs<MemberPointerType>();
-      T1MPType && T2MPType) {
-    if (auto *RD1 = T1MPType->getMostRecentCXXRecordDecl(),
-        *RD2 = T2MPType->getMostRecentCXXRecordDecl();
-        RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
-      return false;
-    if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
-        getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
-      return false;
+  const auto *T1MPType = T1->getAs<MemberPointerType>();
+  const auto *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType &&
+      hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+                             QualType(T2MPType->getClass(), 0))) {
     T1 = T1MPType->getPointeeType();
     T2 = T2MPType->getPointeeType();
     return true;
@@ -13882,12 +13857,11 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
   case Type::MemberPointer: {
     const auto *PX = cast<MemberPointerType>(X),
                *PY = cast<MemberPointerType>(Y);
-    assert(declaresSameEntity(PX->getMostRecentCXXRecordDecl(),
-                              PY->getMostRecentCXXRecordDecl()));
     return Ctx.getMemberPointerType(
         getCommonPointeeType(Ctx, PX, PY),
-        getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true),
-        PX->getMostRecentCXXRecordDec...
[truncated]

@Endilll
Copy link
Contributor

Endilll commented Mar 20, 2025

This missed updating lldb, which we didn't notice due to lack of pre-commit CI.

This is unfortunate, because lack of lldb testing on clang changes was a temporary measure that has been in effect for 8 months at this point (#95537).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:as-a-library libclang and C++ API clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:openmp OpenMP related changes to Clang clang:static analyzer clang Clang issues not falling into any other category clang-tidy clang-tools-extra clangd
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants