https://github.com/mizvekov created https://github.com/llvm/llvm-project/pull/132317
Relands Original PR: https://github.com/llvm/llvm-project/pull/131965 Addresses https://github.com/llvm/llvm-project/pull/131965#issuecomment-2741619498 * Fixes isIncompleteType for injected classes This clears up some uses of getClass on MemberPointerType when equivalent uses of getMostRecentCXXRecordDecl would be just as simple or simpler. This is split-off from a larger patch which removes getClass, in order to facilitate review. >From 52fe0380be295619f3c914e0ad4233d66dd7f361 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Tue, 18 Mar 2025 19:44:23 -0300 Subject: [PATCH 1/2] Reland: [clang] NFC: Clear some uses of MemberPointerType::getClass Original PR: https://github.com/llvm/llvm-project/pull/131965 Addresses https://github.com/llvm/llvm-project/pull/131965#issuecomment-2741619498 * Fixes isIncompleteType for injected classes This clears up some uses of getClass on MemberPointerType when equivalent uses of getMostRecentCXXRecordDecl would be just as simple or simpler. This is split-off from a larger patch which removes getClass, in order to facilitate review. --- ...arePointerToMemberVirtualFunctionCheck.cpp | 5 +- .../clang-tidy/utils/ExceptionAnalyzer.cpp | 4 +- clang/include/clang/AST/CanonicalType.h | 2 + clang/include/clang/Sema/Sema.h | 7 +-- clang/lib/AST/ByteCode/Compiler.cpp | 10 ++-- clang/lib/AST/ExprConstant.cpp | 5 +- clang/lib/AST/MicrosoftMangle.cpp | 10 ++-- clang/lib/AST/Type.cpp | 20 ++++---- clang/lib/CodeGen/CGCXXABI.cpp | 5 +- clang/lib/CodeGen/CGClass.cpp | 7 ++- clang/lib/CodeGen/CGDebugInfo.cpp | 3 +- clang/lib/CodeGen/CGExprCXX.cpp | 8 ++-- clang/lib/CodeGen/CodeGenTypes.cpp | 2 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 11 +++-- clang/lib/Sema/SemaDeclCXX.cpp | 48 +++++++++---------- clang/lib/Sema/SemaExprCXX.cpp | 32 +++++++------ clang/lib/Sema/SemaLookup.cpp | 7 +-- clang/lib/Sema/SemaOverload.cpp | 37 +++++++------- clang/lib/Sema/SemaStmt.cpp | 3 +- 19 files changed, 114 insertions(+), 112 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp index 9d1d92b989bf1..a8a9e6bdcdff8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp @@ -70,10 +70,7 @@ void ComparePointerToMemberVirtualFunctionCheck::check( // compare with variable which type is pointer to member function. llvm::SmallVector<SourceLocation, 12U> SameSignatureVirtualMethods{}; const auto *MPT = cast<MemberPointerType>(DRE->getType().getCanonicalType()); - const Type *T = MPT->getClass(); - if (T == nullptr) - return; - const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); if (RD == nullptr) return; diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 0fea7946a59f9..b66cc8512fad6 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -219,8 +219,8 @@ bool isQualificationConvertiblePointer(QualType From, QualType To, if (P1->isMemberPointerType()) return P2->isMemberPointerType() && - P1->getAs<MemberPointerType>()->getClass() == - P2->getAs<MemberPointerType>()->getClass(); + P1->getAs<MemberPointerType>()->getMostRecentCXXRecordDecl() == + P2->getAs<MemberPointerType>()->getMostRecentCXXRecordDecl(); if (P1->isConstantArrayType()) return P2->isConstantArrayType() && diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index 6699284d215bd..50d1ba1b8f63f 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -454,6 +454,8 @@ 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(const CXXRecordDecl *, + getMostRecentCXXRecordDecl) }; // CanProxyAdaptors for arrays are intentionally unimplemented because diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0befe615c4ee1..9724f0def743a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5769,10 +5769,11 @@ class Sema final : public SemaBase { /// Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. + bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, + CXXRecordDecl *Base, CXXBasePaths &Paths); + bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, + CXXRecordDecl *Base); bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base); - - /// Determine whether the type \p Derived is a C++ class that is - /// derived from the type \p Base. bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, CXXBasePaths &Paths); diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 91640c4eb5cf9..9dc02b25f8495 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -238,8 +238,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>(); const auto *ToMP = CE->getType()->getAs<MemberPointerType>(); - unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), - QualType(FromMP->getClass(), 0)); + unsigned DerivedOffset = + Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(), + FromMP->getMostRecentCXXRecordDecl()); if (!this->delegate(SubExpr)) return false; @@ -253,8 +254,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>(); const auto *ToMP = CE->getType()->getAs<MemberPointerType>(); - unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), - QualType(ToMP->getClass(), 0)); + unsigned DerivedOffset = + Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(), + ToMP->getMostRecentCXXRecordDecl()); if (!this->delegate(SubExpr)) return false; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0165a0a3b0df3..92a28897cf3ee 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10551,8 +10551,9 @@ bool MemberPointerExprEvaluator::VisitCastExpr(const CastExpr *E) { if (!Result.castToDerived(Derived)) return Error(E); } - const Type *FinalTy = E->getType()->castAs<MemberPointerType>()->getClass(); - if (!Result.castToDerived(FinalTy->getAsCXXRecordDecl())) + if (!Result.castToDerived(E->getType() + ->castAs<MemberPointerType>() + ->getMostRecentCXXRecordDecl())) return Error(E); return true; } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index fe34251688a98..15de407e122d8 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -695,7 +695,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { mangleQualifiers(MPT->getPointeeType().getQualifiers(), true); // Member pointers are suffixed with a back reference to the member // pointer's class name. - mangleName(MPT->getClass()->getAsCXXRecordDecl()); + mangleName(MPT->getMostRecentCXXRecordDecl()); } else mangleQualifiers(Ty->getPointeeType().getQualifiers(), false); } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) { @@ -3331,11 +3331,11 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, manglePointerExtQualifiers(Quals, PointeeType); if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) { Out << '8'; - mangleName(T->getClass()->castAs<RecordType>()->getDecl()); + mangleName(T->getMostRecentCXXRecordDecl()); mangleFunctionType(FPT, nullptr, true); } else { mangleQualifiers(PointeeType.getQualifiers(), true); - mangleName(T->getClass()->castAs<RecordType>()->getDecl()); + mangleName(T->getMostRecentCXXRecordDecl()); mangleType(PointeeType, Range, QMM_Drop); } } @@ -4309,11 +4309,11 @@ void MicrosoftCXXNameMangler::mangleAutoReturnType(const MemberPointerType *T, manglePointerExtQualifiers(Quals, PointeeType); if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) { Out << '8'; - mangleName(T->getClass()->castAs<RecordType>()->getDecl()); + mangleName(T->getMostRecentCXXRecordDecl()); mangleFunctionType(FPT, nullptr, true); } else { mangleQualifiers(PointeeType.getQualifiers(), true); - mangleName(T->getClass()->castAs<RecordType>()->getDecl()); + mangleName(T->getMostRecentCXXRecordDecl()); mangleAutoReturnType(PointeeType, QMM_Drop); } } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 72161c06a88d4..33e7008cc4776 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2446,19 +2446,17 @@ bool Type::isIncompleteType(NamedDecl **Def) const { // Member pointers in the MS ABI have special behavior in // RequireCompleteType: they attach a MSInheritanceAttr to the CXXRecordDecl // to indicate which inheritance model to use. - auto *MPTy = cast<MemberPointerType>(CanonicalType); - const Type *ClassTy = MPTy->getClass(); + // The inheritance attribute might only be present on the most recent + // CXXRecordDecl. + const CXXRecordDecl *RD = + cast<MemberPointerType>(CanonicalType)->getMostRecentCXXRecordDecl(); // Member pointers with dependent class types don't get special treatment. - if (ClassTy->isDependentType()) + if (!RD) return false; - const CXXRecordDecl *RD = ClassTy->getAsCXXRecordDecl(); ASTContext &Context = RD->getASTContext(); // Member pointers not in the MS ABI don't get special treatment. if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) return false; - // The inheritance attribute might only be present on the most recent - // CXXRecordDecl, use that one. - RD = RD->getMostRecentNonInjectedDecl(); // Nothing interesting to do if the inheritance attribute is already set. if (RD->hasAttr<MSInheritanceAttr>()) return false; @@ -4713,7 +4711,8 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { const auto *MPT = cast<MemberPointerType>(T); - LinkageInfo LV = computeTypeLinkageInfo(MPT->getClass()); + LinkageInfo LV = + getDeclLinkageAndVisibility(MPT->getMostRecentCXXRecordDecl()); LV.merge(computeTypeLinkageInfo(MPT->getPointeeType())); return LV; } @@ -5179,7 +5178,10 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { } CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { - return getClass()->getAsCXXRecordDecl()->getMostRecentNonInjectedDecl(); + auto *RD = getClass()->getAsCXXRecordDecl(); + if (!RD) + return nullptr; + return RD->getMostRecentNonInjectedDecl(); } void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 7c6dfc3e59d8c..2777c78d6459d 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -50,8 +50,7 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *MemPtr, const MemberPointerType *MPT) { ErrorUnsupportedABI(CGF, "calls through member pointers"); - const auto *RD = - cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl()); + const auto *RD = MPT->getMostRecentCXXRecordDecl(); ThisPtrForCall = CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); const FunctionProtoType *FPT = @@ -294,7 +293,7 @@ llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { derivedType = E->getType(); const CXXRecordDecl *derivedClass = - derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); + derivedType->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl(); return CGM.GetNonVirtualBaseClassOffset(derivedClass, E->path_begin(), diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index fa69caa41936c..98c93b5bb4883 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -161,10 +161,9 @@ CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base, QualType memberType = memberPtrType->getPointeeType(); CharUnits memberAlign = CGM.getNaturalTypeAlignment(memberType, BaseInfo, TBAAInfo); - memberAlign = - CGM.getDynamicOffsetAlignment(base.getAlignment(), - memberPtrType->getClass()->getAsCXXRecordDecl(), - memberAlign); + memberAlign = CGM.getDynamicOffsetAlignment( + base.getAlignment(), memberPtrType->getMostRecentCXXRecordDecl(), + memberAlign); return Address(ptr, ConvertTypeForMem(memberPtrType->getPointeeType()), memberAlign); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c462b02676813..dcccbc0835d95 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3490,7 +3490,8 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, } } - llvm::DIType *ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U); + llvm::DIType *ClassType = getOrCreateType( + QualType(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0), U); if (Ty->isMemberDataPointerType()) return DBuilder.createMemberPointerType( getOrCreateType(Ty->getPointeeType(), U), ClassType, Size, /*Align=*/0, diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index f71c18a8041b1..5d96959065dd9 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -453,8 +453,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, const auto *MPT = MemFnExpr->getType()->castAs<MemberPointerType>(); const auto *FPT = MPT->getPointeeType()->castAs<FunctionProtoType>(); - const auto *RD = - cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl()); + const auto *RD = MPT->getMostRecentCXXRecordDecl(); // Emit the 'this' pointer. Address This = Address::invalid(); @@ -463,8 +462,9 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(); - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), - QualType(MPT->getClass(), 0)); + EmitTypeCheck( + TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), + QualType(MPT->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0)); // Get the member function pointer. llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index dfbd444a850a5..11cf5758b6d3a 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -728,7 +728,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case Type::MemberPointer: { auto *MPTy = cast<MemberPointerType>(Ty); if (!getCXXABI().isMemberPointerConvertible(MPTy)) { - auto *C = MPTy->getClass(); + auto *C = MPTy->getMostRecentCXXRecordDecl()->getTypeForDecl(); auto Insertion = RecordsWithOpaqueMemberPointers.insert({C, nullptr}); if (Insertion.second) Insertion.first->second = llvm::StructType::create(getLLVMContext()); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7e26a0da3d7d2..a5633f6349ffa 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -628,8 +628,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( const FunctionProtoType *FPT = MPT->getPointeeType()->castAs<FunctionProtoType>(); - auto *RD = - cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl()); + auto *RD = MPT->getMostRecentCXXRecordDecl(); llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1); @@ -798,7 +797,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // Check the function pointer if CFI on member function pointers is enabled. if (ShouldEmitCFICheck) { - CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); if (RD->hasDefinition()) { CodeGenFunction::SanitizerScope SanScope(&CGF); @@ -3799,7 +3798,8 @@ static bool ContainsIncompleteClassType(QualType Ty) { if (const MemberPointerType *MemberPointerTy = dyn_cast<MemberPointerType>(Ty)) { // Check if the class type is incomplete. - const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass()); + const auto *ClassType = cast<RecordType>( + MemberPointerTy->getMostRecentCXXRecordDecl()->getTypeForDecl()); if (IsIncompleteClassType(ClassType)) return true; @@ -4538,7 +4538,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { // attributes of the type pointed to. unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); - const RecordType *ClassType = cast<RecordType>(Ty->getClass()); + const auto *ClassType = + cast<RecordType>(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl()); if (IsIncompleteClassType(ClassType)) Flags |= PTI_ContainingClassIncomplete; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a1551e8027cd3..7b2e0df8cb55d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3069,48 +3069,46 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases); } -bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { +bool Sema::IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, + CXXRecordDecl *Base, CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) return false; - CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); - if (!DerivedRD) - return false; - - CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); - if (!BaseRD) + if (!Base || !Derived) return false; // If either the base or the derived type is invalid, don't try to // check whether one is derived from the other. - if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) + if (Base->isInvalidDecl() || Derived->isInvalidDecl()) return false; // FIXME: In a modules build, do we need the entire path to be visible for us // to be able to use the inheritance relationship? - if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + if (!isCompleteType(Loc, Context.getTypeDeclType(Derived)) && + !Derived->isBeingDefined()) return false; - return DerivedRD->isDerivedFrom(BaseRD); + return Derived->isDerivedFrom(Base, Paths); } -bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, - CXXBasePaths &Paths) { - if (!getLangOpts().CPlusPlus) - return false; - - CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); - if (!DerivedRD) - return false; - - CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); - if (!BaseRD) - return false; +bool Sema::IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, + CXXRecordDecl *Base) { + CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, + /*DetectVirtual=*/false); + return IsDerivedFrom(Loc, Derived, Base, Paths); +} - if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) - return false; +bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { + CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, + /*DetectVirtual=*/false); + return IsDerivedFrom(Loc, Derived->getAsCXXRecordDecl(), + Base->getAsCXXRecordDecl(), Paths); +} - return DerivedRD->isDerivedFrom(BaseRD, Paths); +bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, + CXXBasePaths &Paths) { + return IsDerivedFrom(Loc, Derived->getAsCXXRecordDecl(), + Base->getAsCXXRecordDecl(), Paths); } static void BuildBasePathArray(const CXXBasePath &Path, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index cbea98b8884e9..8f204b949cb2c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6529,7 +6529,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } - QualType Class(MemPtr->getClass(), 0); + CXXRecordDecl *RHSClass = MemPtr->getMostRecentCXXRecordDecl(); // Note: C++ [expr.mptr.oper]p2-3 says that the class type into which the // member pointer points must be completely-defined. However, there is no @@ -6552,15 +6552,16 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } } + CXXRecordDecl *LHSClass = LHSType->getAsCXXRecordDecl(); - if (!Context.hasSameUnqualifiedType(Class, LHSType)) { + if (!declaresSameEntity(LHSClass, RHSClass)) { // If we want to check the hierarchy, we need a complete type. if (RequireCompleteType(Loc, LHSType, diag::err_bad_memptr_lhs, OpSpelling, (int)isIndirect)) { return QualType(); } - if (!IsDerivedFrom(Loc, LHSType, Class)) { + if (!IsDerivedFrom(Loc, LHSClass, RHSClass)) { Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling << (int)isIndirect << LHS.get()->getType(); return QualType(); @@ -6568,13 +6569,14 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, CXXCastPath BasePath; if (CheckDerivedToBaseConversion( - LHSType, Class, Loc, + LHSType, QualType(RHSClass->getTypeForDecl(), 0), Loc, SourceRange(LHS.get()->getBeginLoc(), RHS.get()->getEndLoc()), &BasePath)) return QualType(); // Cast LHS to type of use. - QualType UseType = Context.getQualifiedType(Class, LHSType.getQualifiers()); + QualType UseType = Context.getQualifiedType(RHSClass->getTypeForDecl(), + LHSType.getQualifiers()); if (isIndirect) UseType = Context.getPointerType(UseType); ExprValueKind VK = isIndirect ? VK_PRValue : LHS.get()->getValueKind(); @@ -7531,18 +7533,20 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // (Note that the only kinds of reference-relatedness in scope here are // "same type or derived from".) At any other level, the class must // exactly match. - const Type *Class = nullptr; - QualType Cls1(MemPtr1->getClass(), 0); - QualType Cls2(MemPtr2->getClass(), 0); - if (Context.hasSameType(Cls1, Cls2)) - Class = MemPtr1->getClass(); + CXXRecordDecl *Cls = nullptr, + *Cls1 = MemPtr1->getMostRecentCXXRecordDecl(), + *Cls2 = MemPtr2->getMostRecentCXXRecordDecl(); + if (declaresSameEntity(Cls1, Cls2)) + Cls = Cls1; else if (Steps.empty()) - Class = IsDerivedFrom(Loc, Cls1, Cls2) ? MemPtr1->getClass() : - IsDerivedFrom(Loc, Cls2, Cls1) ? MemPtr2->getClass() : nullptr; - if (!Class) + Cls = IsDerivedFrom(Loc, Cls1, Cls2) ? Cls1 + : IsDerivedFrom(Loc, Cls2, Cls1) ? Cls2 + : nullptr; + if (!Cls) return QualType(); - Steps.emplace_back(Step::MemberPointer, Class); + Steps.emplace_back(Step::MemberPointer, + Context.getTypeDeclType(Cls).getTypePtr()); continue; } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index aecf8ed1b4e4d..59dc6df5fbe9f 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3210,11 +3210,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { // X. case Type::MemberPointer: { const MemberPointerType *MemberPtr = cast<MemberPointerType>(T); - - // Queue up the class type into which this points. - Queue.push_back(MemberPtr->getClass()); - - // And directly continue with the pointee type. + addAssociatedClassesAndNamespaces( + Result, MemberPtr->getMostRecentCXXRecordDecl()); T = MemberPtr->getPointeeType().getTypePtr(); continue; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d73a3b5cf99c4..f185bc3cb358a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1897,7 +1897,8 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, auto ToMPT = CanTo.castAs<MemberPointerType>(); auto FromMPT = CanFrom.castAs<MemberPointerType>(); // A function pointer conversion cannot change the class of the function. - if (ToMPT->getClass() != FromMPT->getClass()) + if (!declaresSameEntity(ToMPT->getMostRecentCXXRecordDecl(), + FromMPT->getMostRecentCXXRecordDecl())) return false; CanTo = ToMPT->getPointeeType(); CanFrom = FromMPT->getPointeeType(); @@ -3290,7 +3291,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) { const auto *FromMember = FromType->castAs<MemberPointerType>(), *ToMember = ToType->castAs<MemberPointerType>(); - if (!Context.hasSameType(FromMember->getClass(), ToMember->getClass())) { + if (!declaresSameEntity(FromMember->getMostRecentCXXRecordDecl(), + ToMember->getMostRecentCXXRecordDecl())) { PDiag << ft_different_class << QualType(ToMember->getClass(), 0) << QualType(FromMember->getClass(), 0); return; @@ -4891,14 +4893,10 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, const auto *ToMemPointer1 = ToType1->castAs<MemberPointerType>(); const auto *FromMemPointer2 = FromType2->castAs<MemberPointerType>(); const auto *ToMemPointer2 = ToType2->castAs<MemberPointerType>(); - const Type *FromPointeeType1 = FromMemPointer1->getClass(); - const Type *ToPointeeType1 = ToMemPointer1->getClass(); - const Type *FromPointeeType2 = FromMemPointer2->getClass(); - const Type *ToPointeeType2 = ToMemPointer2->getClass(); - QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType(); - QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType(); - QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType(); - QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType(); + CXXRecordDecl *FromPointee1 = FromMemPointer1->getMostRecentCXXRecordDecl(); + CXXRecordDecl *ToPointee1 = ToMemPointer1->getMostRecentCXXRecordDecl(); + CXXRecordDecl *FromPointee2 = FromMemPointer2->getMostRecentCXXRecordDecl(); + CXXRecordDecl *ToPointee2 = ToMemPointer2->getMostRecentCXXRecordDecl(); // conversion of A::* to B::* is better than conversion of A::* to C::*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2)) @@ -8872,20 +8870,18 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, /// if any, found in visible type conversion functions found in ArgExpr's type. static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { Qualifiers VRQuals; - const RecordType *TyRec; + CXXRecordDecl *ClassDecl; if (const MemberPointerType *RHSMPType = - ArgExpr->getType()->getAs<MemberPointerType>()) - TyRec = RHSMPType->getClass()->getAs<RecordType>(); + ArgExpr->getType()->getAs<MemberPointerType>()) + ClassDecl = RHSMPType->getMostRecentCXXRecordDecl(); else - TyRec = ArgExpr->getType()->getAs<RecordType>(); - if (!TyRec) { + ClassDecl = ArgExpr->getType()->getAsCXXRecordDecl(); + if (!ClassDecl) { // Just to be safe, assume the worst case. VRQuals.addVolatile(); VRQuals.addRestrict(); return VRQuals; } - - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); if (!ClassDecl->hasDefinition()) return VRQuals; @@ -9878,9 +9874,10 @@ class BuiltinOperatorOverloadBuilder { continue; for (QualType MemPtrTy : CandidateTypes[1].member_pointer_types()) { const MemberPointerType *mptr = cast<MemberPointerType>(MemPtrTy); - QualType C2 = QualType(mptr->getClass(), 0); - C2 = C2.getUnqualifiedType(); - if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2)) + CXXRecordDecl *D1 = C1->getAsCXXRecordDecl(), + *D2 = mptr->getMostRecentCXXRecordDecl(); + if (!declaresSameEntity(D1, D2) && + !S.IsDerivedFrom(CandidateSet.getLocation(), D1, D2)) break; QualType ParamTypes[2] = {PtrTy, MemPtrTy}; // build CV12 T& diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 112eaf758cf36..e1b9ccc693bd5 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -799,7 +799,8 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { // Call is: obj->*method_ptr or obj.*method_ptr const auto *MPT = CalleeBinOp->getRHS()->getType()->castAs<MemberPointerType>(); - CalleeType.This = QualType(MPT->getClass(), 0); + CalleeType.This = + Context.getTypeDeclType(MPT->getMostRecentCXXRecordDecl()); CalleeType.Func = MPT->getPointeeType()->castAs<FunctionProtoType>(); CalleeType.MemberType = FuncType::ft_pointer_to_member; } else if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) { >From 4a6142c712f5b582a4acf54f8764f3d02d3ede0d Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Thu, 20 Mar 2025 22:18:14 -0300 Subject: [PATCH 2/2] fixup! [clang] NFC: Clear some uses of MemberPointerType::getClass --- clang/lib/AST/Type.cpp | 2 +- clang/test/SemaCXX/ms-member-pointer.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/ms-member-pointer.cpp diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 33e7008cc4776..9c5fd2289887c 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2451,7 +2451,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const { const CXXRecordDecl *RD = cast<MemberPointerType>(CanonicalType)->getMostRecentCXXRecordDecl(); // Member pointers with dependent class types don't get special treatment. - if (!RD) + if (!RD || RD->isDependentType()) return false; ASTContext &Context = RD->getASTContext(); // Member pointers not in the MS ABI don't get special treatment. diff --git a/clang/test/SemaCXX/ms-member-pointer.cpp b/clang/test/SemaCXX/ms-member-pointer.cpp new file mode 100644 index 0000000000000..2e179b10020e7 --- /dev/null +++ b/clang/test/SemaCXX/ms-member-pointer.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-windows-msvc -verify -std=c++26 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fdelayed-template-parsing -verify -std=c++26 %s +// expected-no-diagnostics + +namespace dependent_complete { + template <class> struct A { + void f(void (A::*)()) {} + }; +} // namespace dependent_complete _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits