diff options
Diffstat (limited to 'clang/lib')
28 files changed, 292 insertions, 241 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 68a02f3..de868ac 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), - QualType(PY->getClass(), 0)) - .getTypePtr()); + getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true), + PX->getMostRecentCXXRecordDecl()); } case Type::LValueReference: { const auto *PX = cast<LValueReferenceType>(X), diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 514887a..1db30b3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1244,12 +1244,16 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { if (!ToPointeeTypeOrErr) return ToPointeeTypeOrErr.takeError(); - ExpectedTypePtr ClassTypeOrErr = import(T->getClass()); - if (!ClassTypeOrErr) - return ClassTypeOrErr.takeError(); + auto QualifierOrErr = import(T->getQualifier()); + if (!QualifierOrErr) + return QualifierOrErr.takeError(); - return Importer.getToContext().getMemberPointerType(*ToPointeeTypeOrErr, - *ClassTypeOrErr); + auto ClsOrErr = import(T->getMostRecentCXXRecordDecl()); + if (!ClsOrErr) + return ClsOrErr.takeError(); + + return Importer.getToContext().getMemberPointerType( + *ToPointeeTypeOrErr, *QualifierOrErr, *ClsOrErr); } ExpectedType diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index b74f67f..2c2c8fd 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -894,8 +894,12 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(), MemPtr2->getPointeeType())) return false; - if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0), - QualType(MemPtr2->getClass(), 0))) + if (!IsStructurallyEquivalent(Context, MemPtr1->getQualifier(), + MemPtr2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Context, + MemPtr1->getMostRecentCXXRecordDecl(), + MemPtr2->getMostRecentCXXRecordDecl())) return false; break; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c79f3e2..9174025 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3828,7 +3828,16 @@ void CXXNameMangler::mangleType(const IncompleteArrayType *T) { // <pointer-to-member-type> ::= M <class type> <member type> void CXXNameMangler::mangleType(const MemberPointerType *T) { Out << 'M'; - mangleType(QualType(T->getClass(), 0)); + if (auto *RD = T->getMostRecentCXXRecordDecl()) { + mangleCXXRecordDecl(RD); + } else { + NestedNameSpecifier *NNS = T->getQualifier(); + if (auto *II = NNS->getAsIdentifier()) + mangleType(getASTContext().getDependentNameType( + ElaboratedTypeKeyword::None, NNS->getPrefix(), II)); + else + manglePrefix(NNS); + } QualType PointeeType = T->getPointeeType(); if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) { mangleType(FPT); diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index 593f2fc..a256a87 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -297,6 +297,7 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, PrintingPolicy InnerPolicy(Policy); InnerPolicy.SuppressScope = true; + InnerPolicy.SuppressTagKeyword = true; // Nested-name-specifiers are intended to contain minimally-qualified // types. An actual ElaboratedType will not occur, since we'll store diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 7c5c287..4c428cc 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -1076,7 +1076,7 @@ public: void VisitMemberPointerType(const MemberPointerType *T) { AddQualType(T->getPointeeType()); - AddType(T->getClass()); + AddNestedNameSpecifier(T->getQualifier()); VisitType(T); } diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index e4d2a69..3c814b7 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -391,9 +391,10 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, Qualifiers Quals = QT.getQualifiers(); // Fully qualify the pointee and class types. QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); - QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx, - WithGlobalNsPrefix); - QT = Ctx.getMemberPointerType(QT, Class.getTypePtr()); + NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier( + Ctx, MPT->getQualifier(), WithGlobalNsPrefix); + QT = Ctx.getMemberPointerType(QT, Qualifier, + MPT->getMostRecentCXXRecordDecl()); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); return QT; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 33e7008..dee1cb8 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1068,7 +1068,8 @@ public: if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr()) return QualType(T, 0); - return Ctx.getMemberPointerType(pointeeType, T->getClass()); + return Ctx.getMemberPointerType(pointeeType, T->getQualifier(), + T->getMostRecentCXXRecordDecl()); } QualType VisitConstantArrayType(const ConstantArrayType *T) { @@ -4621,8 +4622,15 @@ static CachedProperties computeCachedProperties(const Type *T) { return Cache::get(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { const auto *MPT = cast<MemberPointerType>(T); - return merge(Cache::get(MPT->getClass()), - Cache::get(MPT->getPointeeType())); + CachedProperties Cls = [&] { + if (auto *RD = MPT->getMostRecentCXXRecordDecl()) + return Cache::get(QualType(RD->getTypeForDecl(), 0)); + if (const Type *T = MPT->getQualifier()->getAsType()) + return Cache::get(T); + // Treat as a dependent type. + return CachedProperties(Linkage::External, false); + }(); + return merge(Cls, Cache::get(MPT->getPointeeType())); } case Type::ConstantArray: case Type::IncompleteArray: @@ -5177,8 +5185,26 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { return DK_none; } +bool MemberPointerType::isSugared() const { + CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(), + *D2 = getQualifier()->getAsRecordDecl(); + assert(!D1 == !D2); + return D1 != D2 && D1->getCanonicalDecl() != D2->getCanonicalDecl(); +} + +void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, + const NestedNameSpecifier *Qualifier, + const CXXRecordDecl *Cls) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + ID.AddPointer(Qualifier); + if (Cls) + ID.AddPointer(Cls->getCanonicalDecl()); +} + CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { - auto *RD = getClass()->getAsCXXRecordDecl(); + auto *RD = dyn_cast<MemberPointerType>(getCanonicalTypeInternal()) + ->getQualifier() + ->getAsRecordDecl(); if (!RD) return nullptr; return RD->getMostRecentNonInjectedDecl(); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index dfd1959..3982ca3 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -505,9 +505,9 @@ void TypePrinter::printMemberPointerBefore(const MemberPointerType *T, PrintingPolicy InnerPolicy(Policy); InnerPolicy.IncludeTagDefinition = false; - TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); + T->getQualifier()->print(OS, InnerPolicy); - OS << "::*"; + OS << "*"; } void TypePrinter::printMemberPointerAfter(const MemberPointerType *T, diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 2777c78d..fd35f2a 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -107,7 +107,7 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { return GetBogusMemberPointer(CGM.getContext().getMemberPointerType( - MD->getType(), MD->getParent()->getTypeForDecl())); + MD->getType(), /*Qualifier=*/nullptr, MD->getParent())); } llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 0c63b9d..4b03230 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -394,8 +394,8 @@ llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD, llvm::Type *Ty) { QualType FT = FD->getType(); - FT = getContext().getMemberPointerType( - FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl()); + FT = getContext().getMemberPointerType(FT, /*Qualifier=*/nullptr, + cast<CXXMethodDecl>(FD)->getParent()); return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); } diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index c910893..c7b3695 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -1400,9 +1400,8 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) continue; llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( - Context.getMemberPointerType( - Comps[I].getFunctionDecl()->getType(), - Context.getRecordType(AP.Base).getTypePtr())); + Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(), + /*Qualifier=*/nullptr, AP.Base)); VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); } } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index f88d620..e26c6c3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2667,7 +2667,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) { llvm::Metadata *Id = CreateMetadataIdentifierForType(Context.getMemberPointerType( - MD->getType(), Context.getRecordType(Base).getTypePtr())); + MD->getType(), /*Qualifier=*/nullptr, Base)); F->addTypeMetadata(0, Id); } } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index a5633f6..77e995b 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -810,9 +810,9 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *Bit = Builder.getFalse(); for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) { llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType( - getContext().getMemberPointerType( - MPT->getPointeeType(), - getContext().getRecordType(Base).getTypePtr())); + getContext().getMemberPointerType(MPT->getPointeeType(), + /*Qualifier=*/nullptr, + Base->getCanonicalDecl())); llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); @@ -1220,7 +1220,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) { llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment); QualType SrcType = getContext().getMemberPointerType( - MD->getType(), MD->getParent()->getTypeForDecl()); + MD->getType(), /*Qualifier=*/nullptr, MD->getParent()); return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM); } @@ -5135,7 +5135,7 @@ ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) { .getDecl()); llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD); QualType funcType = CGM.getContext().getMemberPointerType( - MD->getType(), MD->getParent()->getTypeForDecl()); + MD->getType(), /*Qualifier=*/nullptr, MD->getParent()); return CGM.getMemberFunctionPointer(thunk, funcType); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 5cb742a..40371d9 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2928,9 +2928,9 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, if (!MemberPointerPath.empty()) { const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext()); - const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr(); const MemberPointerType *SrcTy = - Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) + Ctx.getMemberPointerType(DstTy->getPointeeType(), /*Qualifier=*/nullptr, + SrcRD) ->castAs<MemberPointerType>(); bool DerivedMember = MP.isMemberPointerToDerivedMember(); @@ -3945,7 +3945,8 @@ static QualType decomposeTypeForEH(ASTContext &Context, QualType T, // for "int A::*" and separately storing the const qualifier. if (const auto *MPTy = T->getAs<MemberPointerType>()) T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(), - MPTy->getClass()); + MPTy->getQualifier(), + MPTy->getMostRecentCXXRecordDecl()); // Pointer types like "const int * const *" are represented by having RTTI // for "const int **" and separately storing the const qualifier. diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 4ba46a9..b77cbdb 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1873,21 +1873,20 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, return CheckAccess(*this, Ovl->getNameLoc(), Entity); } -Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, - QualType Base, QualType Derived, - const CXXBasePath &Path, - unsigned DiagID, bool ForceCheck, - bool ForceUnprivileged) { +Sema::AccessResult Sema::CheckBaseClassAccess( + SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived, + const CXXBasePath &Path, unsigned DiagID, + llvm::function_ref<void(PartialDiagnostic &)> SetupPDiag, bool ForceCheck, + bool ForceUnprivileged) { if (!ForceCheck && !getLangOpts().AccessControl) return AR_accessible; if (Path.Access == AS_public) return AR_accessible; - AccessTarget Entity(Context, AccessTarget::Base, Base->getAsCXXRecordDecl(), - Derived->getAsCXXRecordDecl(), Path.Access); + AccessTarget Entity(Context, AccessTarget::Base, Base, Derived, Path.Access); if (DiagID) - Entity.setDiag(DiagID) << Derived << Base; + SetupPDiag(Entity.setDiag(DiagID)); if (ForceUnprivileged) { switch ( @@ -1904,6 +1903,17 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, return CheckAccess(*this, AccessLoc, Entity); } +Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, + QualType Base, QualType Derived, + const CXXBasePath &Path, + unsigned DiagID, bool ForceCheck, + bool ForceUnprivileged) { + return CheckBaseClassAccess( + AccessLoc, Base->getAsCXXRecordDecl(), Derived->getAsCXXRecordDecl(), + Path, DiagID, [&](PartialDiagnostic &PD) { PD << Derived << Base; }, + ForceCheck, ForceUnprivileged); +} + void Sema::CheckLookupAccess(const LookupResult &R) { assert(getLangOpts().AccessControl && "performing access check without access control"); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 718f6be..a5dbc16 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1788,8 +1788,8 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, FoundOverload)) { CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); - SrcType = Self.Context.getMemberPointerType(Fn->getType(), - Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); + SrcType = Self.Context.getMemberPointerType( + Fn->getType(), /*Qualifier=*/nullptr, M->getParent()); WasOverloadedFunction = true; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 42f0acb..16f0b6d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14314,9 +14314,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl()); CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD); - QualType MPTy = Context.getMemberPointerType( - op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); + op->getType(), DRE->getQualifier(), MD->getParent()); if (getLangOpts().PointerAuthCalls && MD->isVirtual() && !isUnevaluatedContext() && !MPTy->isDependentType()) { @@ -14404,8 +14403,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { // of some class C [...] and if E is a qualified-id, E is // not the un-parenthesized operand of the unary & operator [...] // the id-expression is transformed into a class member access expression. - if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() && - !isa<ParenExpr>(OrigOp.get())) { + if (auto *DRE = dyn_cast<DeclRefExpr>(op); + DRE && DRE->getQualifier() && !isa<ParenExpr>(OrigOp.get())) { DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (dcl->getType()->isReferenceType()) { @@ -14419,8 +14418,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { Ctx = Ctx->getParent(); QualType MPTy = Context.getMemberPointerType( - op->getType(), - Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); + op->getType(), DRE->getQualifier(), cast<CXXRecordDecl>(Ctx)); // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) (void)isCompleteType(OpLoc, MPTy); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f085fac..90a4a5a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7368,6 +7368,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, Qualifiers Quals; /// The class for a pointer-to-member; a constant array type with a bound /// (if any) for an array. + /// FIXME: Store Qualifier for pointer-to-member. const Type *ClassOrBound; Step(Kind K, const Type *ClassOrBound = nullptr) @@ -7378,7 +7379,8 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, case Pointer: return Ctx.getPointerType(T); case MemberPointer: - return Ctx.getMemberPointerType(T, ClassOrBound); + return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr, + ClassOrBound->getAsCXXRecordDecl()); case ObjCPointer: return Ctx.getObjCObjectPointerType(T); case Array: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 890de83..1c771b0 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7366,9 +7366,8 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG, QualType FnPtrType; auto *Method = dyn_cast<CXXMethodDecl>(FD); if (Method && !Method->isStatic()) { - const Type *ClassType = - Context.getTypeDeclType(Method->getParent()).getTypePtr(); - FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType); + FnPtrType = Context.getMemberPointerType( + AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent()); ExprResult ER; { // Build addr_of unary op to correctly handle type checks for member diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 161c0da..670c27f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2243,9 +2243,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() == UO_AddrOf && "Non-address-of operator on non-static member address"); - const Type *ClassType - = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); - FromType = S.Context.getMemberPointerType(FromType, ClassType); + FromType = S.Context.getMemberPointerType( + FromType, /*Qualifier=*/nullptr, Method->getParent()); } else if (isa<UnaryOperator>(From->IgnoreParens())) { assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() == UO_AddrOf && @@ -3293,8 +3292,17 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, *ToMember = ToType->castAs<MemberPointerType>(); if (!declaresSameEntity(FromMember->getMostRecentCXXRecordDecl(), ToMember->getMostRecentCXXRecordDecl())) { - PDiag << ft_different_class << QualType(ToMember->getClass(), 0) - << QualType(FromMember->getClass(), 0); + PDiag << ft_different_class; + if (ToMember->isSugared()) + PDiag << Context.getTypeDeclType( + ToMember->getMostRecentCXXRecordDecl()); + else + PDiag << ToMember->getQualifier(); + if (FromMember->isSugared()) + PDiag << Context.getTypeDeclType( + FromMember->getMostRecentCXXRecordDecl()); + else + PDiag << FromMember->getQualifier(); return; } FromType = FromMember->getPointeeType(); @@ -3535,13 +3543,13 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, // A pointer to member of B can be converted to a pointer to member of D, // where D is derived from B (C++ 4.11p2). - QualType FromClass(FromTypePtr->getClass(), 0); - QualType ToClass(ToTypePtr->getClass(), 0); + CXXRecordDecl *FromClass = FromTypePtr->getMostRecentCXXRecordDecl(); + CXXRecordDecl *ToClass = ToTypePtr->getMostRecentCXXRecordDecl(); - if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && + if (!declaresSameEntity(FromClass, ToClass) && IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) { - ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), - ToClass.getTypePtr()); + ConvertedType = Context.getMemberPointerType( + FromTypePtr->getPointeeType(), FromTypePtr->getQualifier(), ToClass); return true; } @@ -3572,10 +3580,23 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( ToPtrType->getPointeeType())) return MemberPointerConversionResult::DifferentPointee; - QualType FromClass = QualType(FromPtrType->getClass(), 0), - ToClass = QualType(ToPtrType->getClass(), 0); + CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(), + *ToClass = ToPtrType->getMostRecentCXXRecordDecl(); + + auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual, + const CXXRecordDecl *Cls) { + if (declaresSameEntity(Qual->getAsRecordDecl(), Cls)) + PD << Qual; + else + PD << QualType(Cls->getTypeForDecl(), 0); + }; + auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & { + DiagCls(PD, FromPtrType->getQualifier(), FromClass); + DiagCls(PD, ToPtrType->getQualifier(), ToClass); + return PD; + }; - QualType Base = FromClass, Derived = ToClass; + CXXRecordDecl *Base = FromClass, *Derived = ToClass; if (Direction == MemberPointerConversionDirection::Upcast) std::swap(Base, Derived); @@ -3584,16 +3605,19 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths)) return MemberPointerConversionResult::NotDerived; - if (Paths.isAmbiguous(Base->getCanonicalTypeUnqualified())) { - Diag(CheckLoc, diag::err_ambiguous_memptr_conv) - << int(Direction) << FromClass << ToClass - << getAmbiguousPathsDisplayString(Paths) << OpRange; + if (Paths.isAmbiguous( + Base->getTypeForDecl()->getCanonicalTypeUnqualified())) { + PartialDiagnostic PD = PDiag(diag::err_ambiguous_memptr_conv); + PD << int(Direction); + DiagFromTo(PD) << getAmbiguousPathsDisplayString(Paths) << OpRange; + Diag(CheckLoc, PD); return MemberPointerConversionResult::Ambiguous; } if (const RecordType *VBase = Paths.getDetectedVirtual()) { - Diag(CheckLoc, diag::err_memptr_conv_via_virtual) - << FromClass << ToClass << QualType(VBase, 0) << OpRange; + PartialDiagnostic PD = PDiag(diag::err_memptr_conv_via_virtual); + DiagFromTo(PD) << QualType(VBase, 0) << OpRange; + Diag(CheckLoc, PD); return MemberPointerConversionResult::Virtual; } @@ -3608,7 +3632,15 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( CheckLoc, Base, Derived, Paths.front(), Direction == MemberPointerConversionDirection::Upcast ? diag::err_upcast_to_inaccessible_base - : diag::err_downcast_from_inaccessible_base)) { + : diag::err_downcast_from_inaccessible_base, + [&](PartialDiagnostic &PD) { + NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(), + *DerivedQual = ToPtrType->getQualifier(); + if (Direction == MemberPointerConversionDirection::Upcast) + std::swap(BaseQual, DerivedQual); + DiagCls(PD, DerivedQual, Derived); + DiagCls(PD, BaseQual, Base); + })) { case Sema::AR_accessible: case Sema::AR_delayed: case Sema::AR_dependent: @@ -8727,7 +8759,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( // and those shouldn't have qualifier variants anyway. if (PointeeTy->isArrayType()) return true; - const Type *ClassTy = PointerTy->getClass(); + CXXRecordDecl *Cls = PointerTy->getMostRecentCXXRecordDecl(); // Iterate through all strict supersets of the pointee type's CVR // qualifiers. @@ -8737,7 +8769,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); MemberPointerTypes.insert( - Context.getMemberPointerType(QPointeeTy, ClassTy)); + Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls)); } return true; @@ -16431,16 +16463,17 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, assert(isa<DeclRefExpr>(SubExpr.get()) && "fixed to something other than a decl ref"); - assert(cast<DeclRefExpr>(SubExpr.get())->getQualifier() && + NestedNameSpecifier *Qualifier = + cast<DeclRefExpr>(SubExpr.get())->getQualifier(); + assert(Qualifier && "fixed to a member ref with no nested name qualifier"); // We have taken the address of a pointer to member // function. Perform the computation here so that we get the // appropriate pointer to member type. - QualType ClassType - = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); - QualType MemPtrType - = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); + QualType MemPtrType = Context.getMemberPointerType( + Fn->getType(), Qualifier, + cast<CXXRecordDecl>(Method->getDeclContext())); // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) (void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c3c993d..45fb9d0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5923,8 +5923,12 @@ bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType( } bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType( - const MemberPointerType* T) { - return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0)); + const MemberPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + if (auto *RD = T->getMostRecentCXXRecordDecl()) + return VisitTagDecl(RD); + return VisitNestedNameSpecifier(T->getQualifier()); } bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType( diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index e6ec4a7..c3bec6b 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2127,9 +2127,19 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( /*DeducedFromArrayBound=*/false, HasDeducedAnyParam); Result != TemplateDeductionResult::Success) return Result; + const Type *QP = MPP->getQualifier()->getAsType(), + *QA = MPA->getQualifier()->getAsType(); + CXXRecordDecl *ClsP = MPP->getMostRecentCXXRecordDecl(), + *ClsA = MPA->getMostRecentCXXRecordDecl(); + // FIXME: Don't drop the rest of the prefixes here. + QualType P = !ClsP || declaresSameEntity(QP->getAsCXXRecordDecl(), ClsP) + ? QualType(QP, 0) + : S.Context.getTypeDeclType(ClsP); + QualType A = !ClsA || declaresSameEntity(QA->getAsCXXRecordDecl(), ClsA) + ? QualType(QA, 0) + : S.Context.getTypeDeclType(ClsA); return DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, QualType(MPP->getClass(), 0), - QualType(MPA->getClass(), 0), Info, Deduced, SubTDF, + S, TemplateParams, P, A, Info, Deduced, SubTDF, degradeCallPartialOrderingKind(POK), /*DeducedFromArrayBound=*/false, HasDeducedAnyParam); } @@ -4211,8 +4221,8 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, if (!R.HasFormOfMemberPointer) return {}; - return S.Context.getMemberPointerType(Fn->getType(), - S.Context.getTypeDeclType(Method->getParent()).getTypePtr()); + return S.Context.getMemberPointerType( + Fn->getType(), /*Qualifier=*/nullptr, Method->getParent()); } if (!R.IsAddressOfOperand) return Fn->getType(); @@ -6833,7 +6843,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr()); MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced, Depth, Used); - MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0), + MarkUsedTemplateParameters(Ctx, + QualType(MemPtr->getQualifier()->getAsType(), 0), OnlyDeduced, Depth, Used); break; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 11943c0..3971738 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2086,7 +2086,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, // an inheritance model, even if it's inside an unused typedef. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) - if (!MPTy->getClass()->isDependentType()) + if (!MPTy->getQualifier()->isDependent()) (void)isCompleteType(Loc, T); } else { @@ -2685,8 +2685,9 @@ QualType Sema::BuildFunctionType(QualType T, return Context.getFunctionType(T, ParamTypes, EPI); } -QualType Sema::BuildMemberPointerType(QualType T, QualType Class, - SourceLocation Loc, +QualType Sema::BuildMemberPointerType(QualType T, + NestedNameSpecifier *Qualifier, + CXXRecordDecl *Cls, SourceLocation Loc, DeclarationName Entity) { // Verify that we're not building a pointer to pointer to function with // exception specification. @@ -2709,11 +2710,6 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, return QualType(); } - if (!Class->isDependentType() && !Class->isRecordType()) { - Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class; - return QualType(); - } - if (T->isFunctionType() && getLangOpts().OpenCL && !getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers", getLangOpts())) { @@ -2734,7 +2730,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, if (T->isFunctionType()) adjustMemberFunctionCC(T, /*HasThisPointer=*/true, IsCtorOrDtor, Loc); - return Context.getMemberPointerType(T, Class.getTypePtr()); + return Context.getMemberPointerType(T, Qualifier, Cls); } QualType Sema::BuildBlockPointerType(QualType T, @@ -5338,7 +5334,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorChunk::MemberPointer: { // The scope spec must refer to a class, or be dependent. CXXScopeSpec &SS = DeclType.Mem.Scope(); - QualType ClsType; // Handle pointer nullability. inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc, @@ -5348,56 +5343,22 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (SS.isInvalid()) { // Avoid emitting extra errors if we already errored on the scope. D.setInvalidType(true); - } else if (S.isDependentScopeSpecifier(SS) || - isa_and_nonnull<CXXRecordDecl>(S.computeDeclContext(SS))) { - NestedNameSpecifier *NNS = SS.getScopeRep(); - NestedNameSpecifier *NNSPrefix = NNS->getPrefix(); - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - ClsType = Context.getDependentNameType( - ElaboratedTypeKeyword::None, NNSPrefix, NNS->getAsIdentifier()); - break; - - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - llvm_unreachable("Nested-name-specifier must name a type"); - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - const Type *NNSType = NNS->getAsType(); - ClsType = QualType(NNSType, 0); - // Note: if the NNS has a prefix and ClsType is a nondependent - // TemplateSpecializationType or a RecordType, then the NNS prefix is - // NOT included in ClsType; hence we wrap ClsType into an - // ElaboratedType. NOTE: in particular, no wrap occurs if ClsType - // already is an Elaborated, DependentName, or - // DependentTemplateSpecialization. - if (isa<DependentTemplateSpecializationType>(NNSType)) { - // FIXME: Rebuild DependentTemplateSpecializationType, adding the - // Prefix. - } else if (isa<TemplateSpecializationType, RecordType>(NNSType)) { - // Either the dependent case (TemplateSpecializationType), or the - // non-dependent one (RecordType). - ClsType = Context.getElaboratedType(ElaboratedTypeKeyword::None, - NNSPrefix, ClsType); - } - break; - } + AreDeclaratorChunksValid = false; + } else if (auto *RD = + dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS)); + RD || S.isDependentScopeSpecifier(SS)) { + T = S.BuildMemberPointerType(T, SS.getScopeRep(), RD, DeclType.Loc, + D.getIdentifier()); } else { S.Diag(DeclType.Mem.Scope().getBeginLoc(), diag::err_illegal_decl_mempointer_in_nonclass) << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name") << DeclType.Mem.Scope().getRange(); D.setInvalidType(true); - } - - if (!ClsType.isNull()) - T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, - D.getIdentifier()); - else AreDeclaratorChunksValid = false; + // FIXME: Maybe we could model these as as a MemberPointerType with a + // non-dependent, non-class qualifier anyway. + } if (T.isNull()) { T = Context.IntTy; @@ -6184,48 +6145,8 @@ namespace { } void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::MemberPointer); - const CXXScopeSpec& SS = Chunk.Mem.Scope(); - NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context); - - const Type* ClsTy = TL.getClass(); - QualType ClsQT = QualType(ClsTy, 0); - TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0); - // Now copy source location info into the type loc component. - TypeLoc ClsTL = ClsTInfo->getTypeLoc(); - switch (NNSLoc.getNestedNameSpecifier()->getKind()) { - case NestedNameSpecifier::Identifier: - assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc"); - { - DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>(); - DNTLoc.setElaboratedKeywordLoc(SourceLocation()); - DNTLoc.setQualifierLoc(NNSLoc.getPrefix()); - DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc()); - } - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - if (isa<ElaboratedType>(ClsTy)) { - ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>(); - ETLoc.setElaboratedKeywordLoc(SourceLocation()); - ETLoc.setQualifierLoc(NNSLoc.getPrefix()); - TypeLoc NamedTL = ETLoc.getNamedTypeLoc(); - NamedTL.initializeFullCopy(NNSLoc.getTypeLoc()); - } else { - ClsTL.initializeFullCopy(NNSLoc.getTypeLoc()); - } - break; - - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - llvm_unreachable("Nested-name-specifier must name a type"); - } - - // Finally fill in MemberPointerLocInfo fields. TL.setStarLoc(Chunk.Mem.StarLoc); - TL.setClassTInfo(ClsTInfo); + TL.setQualifierLoc(Chunk.Mem.Scope().getWithLocInContext(Context)); } void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Reference); @@ -7054,7 +6975,8 @@ namespace { case MemberPointer: { const MemberPointerType *OldMPT = cast<MemberPointerType>(Old); QualType New = wrap(C, OldMPT->getPointeeType(), I); - return C.getMemberPointerType(New, OldMPT->getClass()); + return C.getMemberPointerType(New, OldMPT->getQualifier(), + OldMPT->getMostRecentCXXRecordDecl()); } case Reference: { @@ -9333,17 +9255,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // "Can't ask whether a dependent type is complete"); if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) { - if (!MPTy->getClass()->isDependentType()) { + if (!MPTy->getQualifier()->isDependent()) { + QualType T = Context.getTypeDeclType(MPTy->getMostRecentCXXRecordDecl()); if (getLangOpts().CompleteMemberPointers && - !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() && - RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), Kind, - diag::err_memptr_incomplete)) + !MPTy->getMostRecentCXXRecordDecl()->isBeingDefined() && + RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete)) return true; // We lock in the inheritance model once somebody has asked us to ensure // that a pointer-to-member type is complete. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0)); + (void)isCompleteType(Loc, T); assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl()); } } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b5de98e..5686b9d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -859,12 +859,13 @@ public: SourceLocation Sigil); /// Build a new member pointer type given the pointee type and the - /// class type it refers into. + /// qualifier it refers into. /// /// By default, performs semantic analysis when building the member pointer /// type. Subclasses may override this routine to provide different behavior. - QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, - SourceLocation Sigil); + QualType RebuildMemberPointerType(QualType PointeeType, + NestedNameSpecifier *Qualifier, + CXXRecordDecl *Cls, SourceLocation Sigil); QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc, @@ -5607,31 +5608,30 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); - TypeSourceInfo* OldClsTInfo = TL.getClassTInfo(); - TypeSourceInfo *NewClsTInfo = nullptr; - if (OldClsTInfo) { - NewClsTInfo = getDerived().TransformType(OldClsTInfo); - if (!NewClsTInfo) - return QualType(); - } - const MemberPointerType *T = TL.getTypePtr(); - QualType OldClsType = QualType(T->getClass(), 0); - QualType NewClsType; - if (NewClsTInfo) - NewClsType = NewClsTInfo->getType(); - else { - NewClsType = getDerived().TransformType(OldClsType); - if (NewClsType.isNull()) + + NestedNameSpecifierLoc OldQualifierLoc = TL.getQualifierLoc(); + NestedNameSpecifierLoc NewQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(OldQualifierLoc); + if (!NewQualifierLoc) + return QualType(); + + CXXRecordDecl *OldCls = T->getMostRecentCXXRecordDecl(), *NewCls = nullptr; + if (OldCls) { + NewCls = cast_or_null<CXXRecordDecl>( + getDerived().TransformDecl(TL.getStarLoc(), OldCls)); + if (!NewCls) return QualType(); } QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - PointeeType != T->getPointeeType() || - NewClsType != OldClsType) { - Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType, - TL.getStarLoc()); + if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() || + NewQualifierLoc.getNestedNameSpecifier() != + OldQualifierLoc.getNestedNameSpecifier() || + NewCls != OldCls) { + Result = getDerived().RebuildMemberPointerType( + PointeeType, NewQualifierLoc.getNestedNameSpecifier(), NewCls, + TL.getStarLoc()); if (Result.isNull()) return QualType(); } @@ -5646,7 +5646,7 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result); NewTL.setSigilLoc(TL.getSigilLoc()); - NewTL.setClassTInfo(NewClsTInfo); + NewTL.setQualifierLoc(NewQualifierLoc); return Result; } @@ -17040,12 +17040,11 @@ TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType, Sigil, getDerived().getBaseEntity()); } -template<typename Derived> -QualType -TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, - QualType ClassType, - SourceLocation Sigil) { - return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil, +template <typename Derived> +QualType TreeTransform<Derived>::RebuildMemberPointerType( + QualType PointeeType, NestedNameSpecifier *Qualifier, CXXRecordDecl *Cls, + SourceLocation Sigil) { + return SemaRef.BuildMemberPointerType(PointeeType, Qualifier, Cls, Sigil, getDerived().getBaseEntity()); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 2b03446..e53a30c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7103,7 +7103,7 @@ void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { TL.setStarLoc(readSourceLocation()); - TL.setClassTInfo(GetTypeSourceInfo()); + TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); } void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 9e6da4d..1ffa17d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -409,7 +409,7 @@ void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { addSourceLocation(TL.getStarLoc()); - Record.AddTypeSourceInfo(TL.getClassTInfo()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); } void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { diff --git a/clang/lib/Serialization/TemplateArgumentHasher.cpp b/clang/lib/Serialization/TemplateArgumentHasher.cpp index 598f098..3c7177b 100644 --- a/clang/lib/Serialization/TemplateArgumentHasher.cpp +++ b/clang/lib/Serialization/TemplateArgumentHasher.cpp @@ -317,7 +317,9 @@ public: void VisitMemberPointerType(const MemberPointerType *T) { AddQualType(T->getPointeeType()); - AddType(T->getClass()); + AddType(T->getQualifier()->getAsType()); + if (auto *RD = T->getMostRecentCXXRecordDecl()) + AddDecl(RD->getCanonicalDecl()); } void VisitPackExpansionType(const PackExpansionType *T) { |