[Lldb-commits] [clang] [clang-tools-extra] [lldb] Reland: [clang] preserve class type sugar when taking pointer to member (PR #132234)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Mar 20 08:06:35 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
Original PR: #<!-- -->130537
Reland after updating lldb too.
This changes the MemberPointerType representation to use a NestedNameSpecifier instead of a Type to represent the base class.
Since the qualifiers are always parsed as nested names, there was an impedance mismatch when converting these back and forth into types, and this led to issues in preserving sugar.
The nested names are indeed a better match for these, as the differences which a QualType can represent cannot be expressed syntatically, and they represent the use case more exactly, being either dependent or referring to a CXXRecord, unqualified.
This patch also makes the MemberPointerType able to represent sugar for a {up/downcast}cast conversion of the base class, although for now the underlying type is canonical, as preserving the sugar up to that point requires further work.
As usual, includes a few drive-by fixes in order to make use of the improvements.
---
Patch is 143.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132234.diff
71 Files Affected:
- (modified) clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp (+1-2)
- (modified) clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp (+3-1)
- (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+1-1)
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/include/clang/AST/ASTContext.h (+3-4)
- (modified) clang/include/clang/AST/ASTNodeTraverser.h (+5-2)
- (modified) clang/include/clang/AST/CanonicalType.h (+1-1)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+5-4)
- (modified) clang/include/clang/AST/Type.h (+15-13)
- (modified) clang/include/clang/AST/TypeLoc.h (+19-14)
- (modified) clang/include/clang/AST/TypeProperties.td (+6-3)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-4)
- (modified) clang/include/clang/Sema/Sema.h (+9-2)
- (modified) clang/lib/AST/ASTContext.cpp (+47-21)
- (modified) clang/lib/AST/ASTImporter.cpp (+9-5)
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+6-2)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+10-1)
- (modified) clang/lib/AST/NestedNameSpecifier.cpp (+1)
- (modified) clang/lib/AST/ODRHash.cpp (+1-1)
- (modified) clang/lib/AST/QualTypeNames.cpp (+4-3)
- (modified) clang/lib/AST/Type.cpp (+30-4)
- (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 (+2-3)
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+5-5)
- (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+4-3)
- (modified) clang/lib/Sema/SemaAccess.cpp (+18-8)
- (modified) clang/lib/Sema/SemaCast.cpp (+2-2)
- (modified) clang/lib/Sema/SemaExpr.cpp (+4-6)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+3-1)
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+2-3)
- (modified) clang/lib/Sema/SemaOverload.cpp (+60-27)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+6-2)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+16-5)
- (modified) clang/lib/Sema/SemaType.cpp (+22-100)
- (modified) clang/lib/Sema/TreeTransform.h (+29-30)
- (modified) clang/lib/Serialization/ASTReader.cpp (+1-1)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+1-1)
- (modified) clang/lib/Serialization/TemplateArgumentHasher.cpp (+3-1)
- (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+3-1)
- (modified) clang/test/AST/ast-dump-templates.cpp (+238)
- (modified) clang/test/AST/ast-dump-types-json.cpp (+338-44)
- (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 (+1-2)
- (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 (+13-4)
- (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 (+2-1)
- (modified) clang/tools/libclang/CXType.cpp (+3-1)
- (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+4-4)
- (modified) lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp (+1-1)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+4-3)
``````````diff
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 108717e151b57..a6b00be75abf8 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,8 +493,7 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
NullMacrosStr(Options.get("NullMacros", "NULL")),
IgnoredTypes(utils::options::parseStringList(Options.get(
- "IgnoredTypes",
- "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
+ "IgnoredTypes", "_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 b66cc8512fad6..bc49fa856bafc 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,7 +178,9 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
// Note: converting Derived::* to Base::* is a different kind of conversion,
// called Pointer-to-member conversion.
- return FromMember->getClass() == ToMember->getClass() &&
+ return FromMember->getQualifier() == ToMember->getQualifier() &&
+ FromMember->getMostRecentCXXRecordDecl() ==
+ ToMember->getMostRecentCXXRecordDecl() &&
FromMember->getPointeeType() == ToMember->getPointeeType();
}
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index fc54f89f4941e..602f61d9ecb41 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 = 'struct S::'\n"
+ "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
"8: targets = {y}, decl\n"},
{R"cpp(
void foo() {
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 88862f7661191..97f6ea90d4705 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -267,6 +267,7 @@ 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 f9a12260a6590..af8c49e99a7ce 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,10 +1558,9 @@ 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 class.
- ///
- /// The class \p Cls is a \c Type because it could be a dependent name.
- QualType getMemberPointerType(QualType T, const Type *Cls) const;
+ /// the specified type in the specified nested name.
+ QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *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 3bc0bdff2bdd1..f557555e96e59 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,7 +393,9 @@ class ASTNodeTraverser
Visit(T->getPointeeType());
}
void VisitMemberPointerType(const MemberPointerType *T) {
- Visit(T->getClass());
+ // FIXME: Provide a NestedNameSpecifier visitor.
+ Visit(T->getQualifier()->getAsType());
+ Visit(T->getMostRecentCXXRecordDecl());
Visit(T->getPointeeType());
}
void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -485,7 +487,8 @@ class ASTNodeTraverser
}
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
- Visit(TL.getClassTInfo()->getTypeLoc());
+ // FIXME: Provide NestedNamespecifierLoc visitor.
+ Visit(TL.getQualifierLoc().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 50d1ba1b8f63f..35db68971e029 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(const Type *, getClass)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
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 87a6c22b35ee8..e93d1d8eab56f 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,7 +1004,8 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
{ TRY_TO(TraverseType(T->getPointeeType())); })
DEF_TRAVERSE_TYPE(MemberPointerType, {
- TRY_TO(TraverseType(QualType(T->getClass(), 0)));
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
TRY_TO(TraverseType(T->getPointeeType()));
})
@@ -1269,10 +1270,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 (auto *TSI = TL.getClassTInfo())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
+ TRY_TO(TraverseNestedNameSpecifierLoc(QL));
else
- TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+ TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 3c942f2ed7486..65756203f2073 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3527,14 +3527,16 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
/// The class of which the pointee is a member. Must ultimately be a
- /// RecordType, but could be a typedef or a template parameter too.
- const Type *Class;
+ /// CXXRecordType, but could be a typedef or a template parameter too.
+ NestedNameSpecifier *Qualifier;
- MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
+ MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
+ QualType CanonicalPtr)
: Type(MemberPointer, CanonicalPtr,
- (Cls->getDependence() & ~TypeDependence::VariablyModified) |
+ (toTypeDependence(Qualifier->getDependence()) &
+ ~TypeDependence::VariablyModified) |
Pointee->getDependence()),
- PointeeType(Pointee), Class(Cls) {}
+ PointeeType(Pointee), Qualifier(Qualifier) {}
public:
QualType getPointeeType() const { return PointeeType; }
@@ -3551,21 +3553,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
return !PointeeType->isFunctionProtoType();
}
- const Type *getClass() const { return Class; }
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
CXXRecordDecl *getMostRecentCXXRecordDecl() const;
- bool isSugared() const { return false; }
- QualType desugar() const { return QualType(this, 0); }
+ bool isSugared() const;
+ QualType desugar() const {
+ return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getPointeeType(), getClass());
+ Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
- const Type *Class) {
- ID.AddPointer(Pointee.getAsOpaquePtr());
- ID.AddPointer(Class);
- }
+ const NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls);
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 a55a38335ef6a..17ce09fa5da4f 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -139,6 +139,7 @@ class TypeLoc {
}
/// Get the pointer where source information is stored.
+ // FIXME: This should provide a type-safe interface.
void *getOpaqueData() const {
return Data;
}
@@ -1355,7 +1356,7 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
};
struct MemberPointerLocInfo : public PointerLikeLocInfo {
- TypeSourceInfo *ClassTInfo;
+ void *QualifierData = nullptr;
};
/// Wrapper for source info for member pointers.
@@ -1371,28 +1372,32 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
setSigilLoc(Loc);
}
- const Type *getClass() const {
- return getTypePtr()->getClass();
- }
-
- TypeSourceInfo *getClassTInfo() const {
- return getLocalData()->ClassTInfo;
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
+ getLocalData()->QualifierData);
}
- void setClassTInfo(TypeSourceInfo* TI) {
- getLocalData()->ClassTInfo = TI;
+ void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
+ assert(QualifierLoc.getNestedNameSpecifier() ==
+ getTypePtr()->getQualifier() &&
+ "Inconsistent nested-name-specifier pointer");
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
- setClassTInfo(nullptr);
+ if (auto *Qualifier = getTypePtr()->getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, Qualifier, Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ } else
+ getLocalData()->QualifierData = nullptr;
}
SourceRange getLocalSourceRange() const {
- if (TypeSourceInfo *TI = getClassTInfo())
- return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
- else
- return SourceRange(getStarLoc());
+ if (NestedNameSpecifierLoc QL = getQualifierLoc())
+ return SourceRange(QL.getBeginLoc(), getStarLoc());
+ return SourceRange(getStarLoc());
}
};
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 6f1a76bd18fb5..27f71bf5cc62f 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,12 +100,15 @@ let Class = MemberPointerType in {
def : Property<"pointeeType", QualType> {
let Read = [{ node->getPointeeType() }];
}
- def : Property<"baseType", QualType> {
- let Read = [{ QualType(node->getClass(), 0) }];
+ def : Property<"Qualifier", NestedNameSpecifier> {
+ let Read = [{ node->getQualifier() }];
+ }
+ def : Property<"Cls", DeclRef> {
+ let Read = [{ node->getMostRecentCXXRecordDecl() }];
}
def : Creator<[{
- return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
+ return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
}]>;
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1536a3b8c920a..4cb8f3d759817 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7065,10 +7065,8 @@ 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_mempointer_in_nonclass_type : Error<
- "member pointer refers into non-class type %0">;
+def err_illegal_decl_mempointer_in_nonclass
+ : Error<"'%0' does not point into a class">;
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 9724f0def743a..e215f07e2bf0a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,6 +1348,12 @@ 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);
@@ -14879,8 +14885,9 @@ 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, QualType Class,
- SourceLocation Loc, DeclarationName Entity);
+ QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ CXXRecordDecl *Cls, SourceLocation Loc,
+ DeclarationName Entity);
/// Build a block pointer type.
///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 68a02f3bbe1ec..de868ac821745 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3322,7 +3322,8 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
case Type::MemberPointer: {
OS << "M";
const auto *MPT = T->castAs<MemberPointerType>();
- encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
+ encodeTypeForFunctionPointerAuth(
+ Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
return;
}
@@ -3511,7 +3512,8 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) {
if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
EST_None) {
QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
- T = getMemberPointerType(FT, MPT->getClass());
+ T = getMemberPointerType(FT, MPT->getQualifier(),
+ MPT->getMostRecentCXXRecordDecl());
}
}
std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4025,32 +4027,50 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
return QualType(New, 0);
}
-/// 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 {
+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();
+ }
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
- MemberPointerType::Profile(ID, T, Cls);
+ MemberPointerType::Profile(ID, T, Qualifier, 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() || !Cls->isCanonicalUnqualified()) {
- Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
-
+ if (!T.isCanonical() || Qualifier != CanonicalQualifier) {
+ Canonical =
+ getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls);
+ assert(!cast<MemberPointerType>(Canonical)->isSugared());
// Get the new insert position for the node we care about.
- MemberPointerType *NewIP =
- MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
+ [[maybe_unused]] MemberPointerType *NewIP =
+ MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!NewIP && "Shouldn't be in the map!");
}
auto *New = new (*this, alignof(MemberPointerType))
- MemberPointerType(T, Cls, Canonical);
+ MemberPointerType(T, Qualifier, Canonical);
Types.push_back(New);
MemberPointerTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -6812,11 +6832,16 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
return true;
}
- const auto *T1MPType = T1->getAs<MemberPointerType>();
- const auto *T2MPType = T2->getAs<MemberPointerType>();
- if (T1MPType && T2MPType &&
- hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
- QualType(T2MPType->getClass(), 0))) {
+ 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;
T1 = T1MPType->getPointeeType();
T2 = T2MPType->getPointeeType();
return true;
@@ -13857,11 +13882,12 @@ 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),
- Ctx.getCommonSugaredType(QualType(PX->getClass(), 0),
- ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/132234
More information about the lldb-commits
mailing list