diff options
Diffstat (limited to 'clang/lib')
28 files changed, 241 insertions, 292 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index de868ac..68a02f3 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3322,8 +3322,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, case Type::MemberPointer: { OS << "M"; const auto *MPT = T->castAs<MemberPointerType>(); - encodeTypeForFunctionPointerAuth( - Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0)); + encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0)); encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType()); return; } @@ -3512,8 +3511,7 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() != EST_None) { QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None); - T = getMemberPointerType(FT, MPT->getQualifier(), - MPT->getMostRecentCXXRecordDecl()); + T = getMemberPointerType(FT, MPT->getClass()); } } std::unique_ptr<MangleContext> MC(createMangleContext()); @@ -4027,50 +4025,32 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { return QualType(New, 0); } -QualType ASTContext::getMemberPointerType(QualType T, - NestedNameSpecifier *Qualifier, - const CXXRecordDecl *Cls) const { - if (!Qualifier) { - assert(Cls && "At least one of Qualifier or Cls must be provided"); - Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr, - /*Template=*/false, - getTypeDeclType(Cls).getTypePtr()); - } else if (!Cls) { - Cls = Qualifier->getAsRecordDecl(); - } +/// getMemberPointerType - Return the uniqued reference to the type for a +/// member pointer to the specified type, in the specified class. +QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; - MemberPointerType::Profile(ID, T, Qualifier, Cls); + MemberPointerType::Profile(ID, T, Cls); void *InsertPos = nullptr; if (MemberPointerType *PT = MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); - NestedNameSpecifier *CanonicalQualifier = [&] { - if (!Cls) - return getCanonicalNestedNameSpecifier(Qualifier); - NestedNameSpecifier *R = NestedNameSpecifier::Create( - *this, /*Prefix=*/nullptr, /*Template=*/false, - Cls->getCanonicalDecl()->getTypeForDecl()); - assert(R == getCanonicalNestedNameSpecifier(R)); - return R; - }(); // If the pointee or class type isn't canonical, this won't be a canonical // type either, so fill in the canonical type field. QualType Canonical; - if (!T.isCanonical() || Qualifier != CanonicalQualifier) { - Canonical = - getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls); - assert(!cast<MemberPointerType>(Canonical)->isSugared()); + if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) { + Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls)); + // Get the new insert position for the node we care about. - [[maybe_unused]] MemberPointerType *NewIP = - MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!NewIP && "Shouldn't be in the map!"); + MemberPointerType *NewIP = + MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } auto *New = new (*this, alignof(MemberPointerType)) - MemberPointerType(T, Qualifier, Canonical); + MemberPointerType(T, Cls, Canonical); Types.push_back(New); MemberPointerTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -6832,16 +6812,11 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2, return true; } - if (const auto *T1MPType = T1->getAs<MemberPointerType>(), - *T2MPType = T2->getAs<MemberPointerType>(); - T1MPType && T2MPType) { - if (auto *RD1 = T1MPType->getMostRecentCXXRecordDecl(), - *RD2 = T2MPType->getMostRecentCXXRecordDecl(); - RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl()) - return false; - if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) != - getCanonicalNestedNameSpecifier(T2MPType->getQualifier())) - return false; + const auto *T1MPType = T1->getAs<MemberPointerType>(); + const auto *T2MPType = T2->getAs<MemberPointerType>(); + if (T1MPType && T2MPType && + hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0), + QualType(T2MPType->getClass(), 0))) { T1 = T1MPType->getPointeeType(); T2 = T2MPType->getPointeeType(); return true; @@ -13882,12 +13857,11 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, case Type::MemberPointer: { const auto *PX = cast<MemberPointerType>(X), *PY = cast<MemberPointerType>(Y); - assert(declaresSameEntity(PX->getMostRecentCXXRecordDecl(), - PY->getMostRecentCXXRecordDecl())); return Ctx.getMemberPointerType( getCommonPointeeType(Ctx, PX, PY), - getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true), - PX->getMostRecentCXXRecordDecl()); + Ctx.getCommonSugaredType(QualType(PX->getClass(), 0), + QualType(PY->getClass(), 0)) + .getTypePtr()); } case Type::LValueReference: { const auto *PX = cast<LValueReferenceType>(X), diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 1db30b3..514887a 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1244,16 +1244,12 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { if (!ToPointeeTypeOrErr) return ToPointeeTypeOrErr.takeError(); - auto QualifierOrErr = import(T->getQualifier()); - if (!QualifierOrErr) - return QualifierOrErr.takeError(); + ExpectedTypePtr ClassTypeOrErr = import(T->getClass()); + if (!ClassTypeOrErr) + return ClassTypeOrErr.takeError(); - auto ClsOrErr = import(T->getMostRecentCXXRecordDecl()); - if (!ClsOrErr) - return ClsOrErr.takeError(); - - return Importer.getToContext().getMemberPointerType( - *ToPointeeTypeOrErr, *QualifierOrErr, *ClsOrErr); + return Importer.getToContext().getMemberPointerType(*ToPointeeTypeOrErr, + *ClassTypeOrErr); } ExpectedType diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 2c2c8fd..b74f67f 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -894,12 +894,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(), MemPtr2->getPointeeType())) return false; - if (!IsStructurallyEquivalent(Context, MemPtr1->getQualifier(), - MemPtr2->getQualifier())) - return false; - if (!IsStructurallyEquivalent(Context, - MemPtr1->getMostRecentCXXRecordDecl(), - MemPtr2->getMostRecentCXXRecordDecl())) + if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0), + QualType(MemPtr2->getClass(), 0))) return false; break; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 9174025..c79f3e2 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3828,16 +3828,7 @@ void CXXNameMangler::mangleType(const IncompleteArrayType *T) { // <pointer-to-member-type> ::= M <class type> <member type> void CXXNameMangler::mangleType(const MemberPointerType *T) { Out << 'M'; - 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); - } + mangleType(QualType(T->getClass(), 0)); 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 a256a87..593f2fc 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -297,7 +297,6 @@ 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 4c428cc..7c5c287 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()); - AddNestedNameSpecifier(T->getQualifier()); + AddType(T->getClass()); VisitType(T); } diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 3c814b7..e4d2a69 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -391,10 +391,9 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, Qualifiers Quals = QT.getQualifiers(); // Fully qualify the pointee and class types. QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); - NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier( - Ctx, MPT->getQualifier(), WithGlobalNsPrefix); - QT = Ctx.getMemberPointerType(QT, Qualifier, - MPT->getMostRecentCXXRecordDecl()); + QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx, + WithGlobalNsPrefix); + QT = Ctx.getMemberPointerType(QT, Class.getTypePtr()); // 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 dee1cb8..33e7008 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1068,8 +1068,7 @@ public: if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr()) return QualType(T, 0); - return Ctx.getMemberPointerType(pointeeType, T->getQualifier(), - T->getMostRecentCXXRecordDecl()); + return Ctx.getMemberPointerType(pointeeType, T->getClass()); } QualType VisitConstantArrayType(const ConstantArrayType *T) { @@ -4622,15 +4621,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return Cache::get(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { const auto *MPT = cast<MemberPointerType>(T); - 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())); + return merge(Cache::get(MPT->getClass()), + Cache::get(MPT->getPointeeType())); } case Type::ConstantArray: case Type::IncompleteArray: @@ -5185,26 +5177,8 @@ 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 = dyn_cast<MemberPointerType>(getCanonicalTypeInternal()) - ->getQualifier() - ->getAsRecordDecl(); + auto *RD = getClass()->getAsCXXRecordDecl(); if (!RD) return nullptr; return RD->getMostRecentNonInjectedDecl(); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 3982ca3..dfd1959 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; - T->getQualifier()->print(OS, InnerPolicy); + TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); - OS << "*"; + OS << "::*"; } void TypePrinter::printMemberPointerAfter(const MemberPointerType *T, diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index fd35f2a..2777c78d 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(), /*Qualifier=*/nullptr, MD->getParent())); + MD->getType(), MD->getParent()->getTypeForDecl())); } llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 4b03230..0c63b9d 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, /*Qualifier=*/nullptr, - cast<CXXMethodDecl>(FD)->getParent()); + FT = getContext().getMemberPointerType( + FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl()); return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); } diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index c7b3695..c910893 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -1400,8 +1400,9 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) continue; llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( - Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(), - /*Qualifier=*/nullptr, AP.Base)); + Context.getMemberPointerType( + Comps[I].getFunctionDecl()->getType(), + Context.getRecordType(AP.Base).getTypePtr())); VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); } } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 96ab4dd..ecce52e 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(), /*Qualifier=*/nullptr, Base)); + MD->getType(), Context.getRecordType(Base).getTypePtr())); F->addTypeMetadata(0, Id); } } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 77e995b..a5633f6 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(), - /*Qualifier=*/nullptr, - Base->getCanonicalDecl())); + getContext().getMemberPointerType( + MPT->getPointeeType(), + getContext().getRecordType(Base).getTypePtr())); 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(), /*Qualifier=*/nullptr, MD->getParent()); + MD->getType(), MD->getParent()->getTypeForDecl()); 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(), /*Qualifier=*/nullptr, MD->getParent()); + MD->getType(), MD->getParent()->getTypeForDecl()); return CGM.getMemberFunctionPointer(thunk, funcType); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 40371d9..5cb742a 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(), /*Qualifier=*/nullptr, - SrcRD) + Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) ->castAs<MemberPointerType>(); bool DerivedMember = MP.isMemberPointerToDerivedMember(); @@ -3945,8 +3945,7 @@ 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->getQualifier(), - MPTy->getMostRecentCXXRecordDecl()); + MPTy->getClass()); // 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 b77cbdb..4ba46a9 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1873,20 +1873,21 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, return CheckAccess(*this, Ovl->getNameLoc(), Entity); } -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) { +Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, + QualType Base, QualType Derived, + const CXXBasePath &Path, + unsigned DiagID, 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, Derived, Path.Access); + AccessTarget Entity(Context, AccessTarget::Base, Base->getAsCXXRecordDecl(), + Derived->getAsCXXRecordDecl(), Path.Access); if (DiagID) - SetupPDiag(Entity.setDiag(DiagID)); + Entity.setDiag(DiagID) << Derived << Base; if (ForceUnprivileged) { switch ( @@ -1903,17 +1904,6 @@ Sema::AccessResult Sema::CheckBaseClassAccess( 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 a5dbc16..718f6be 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(), /*Qualifier=*/nullptr, M->getParent()); + SrcType = Self.Context.getMemberPointerType(Fn->getType(), + Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); WasOverloadedFunction = true; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 16f0b6d..42f0acb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14314,8 +14314,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl()); CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD); + QualType MPTy = Context.getMemberPointerType( - op->getType(), DRE->getQualifier(), MD->getParent()); + op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); if (getLangOpts().PointerAuthCalls && MD->isVirtual() && !isUnevaluatedContext() && !MPTy->isDependentType()) { @@ -14403,8 +14404,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 (auto *DRE = dyn_cast<DeclRefExpr>(op); - DRE && DRE->getQualifier() && !isa<ParenExpr>(OrigOp.get())) { + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() && + !isa<ParenExpr>(OrigOp.get())) { DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (dcl->getType()->isReferenceType()) { @@ -14418,7 +14419,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { Ctx = Ctx->getParent(); QualType MPTy = Context.getMemberPointerType( - op->getType(), DRE->getQualifier(), cast<CXXRecordDecl>(Ctx)); + op->getType(), + Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); // 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 856b505..8f204b9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7369,7 +7369,6 @@ 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) @@ -7380,8 +7379,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, case Pointer: return Ctx.getPointerType(T); case MemberPointer: - return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr, - ClassOrBound->getAsCXXRecordDecl()); + return Ctx.getMemberPointerType(T, ClassOrBound); case ObjCPointer: return Ctx.getObjCObjectPointerType(T); case Array: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 1c771b0..890de83 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7366,8 +7366,9 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG, QualType FnPtrType; auto *Method = dyn_cast<CXXMethodDecl>(FD); if (Method && !Method->isStatic()) { - FnPtrType = Context.getMemberPointerType( - AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent()); + const Type *ClassType = + Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType); 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 6d8006b..f185bc3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2243,8 +2243,9 @@ 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"); - FromType = S.Context.getMemberPointerType( - FromType, /*Qualifier=*/nullptr, Method->getParent()); + const Type *ClassType + = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FromType = S.Context.getMemberPointerType(FromType, ClassType); } else if (isa<UnaryOperator>(From->IgnoreParens())) { assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() == UO_AddrOf && @@ -3292,17 +3293,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, *ToMember = ToType->castAs<MemberPointerType>(); if (!declaresSameEntity(FromMember->getMostRecentCXXRecordDecl(), ToMember->getMostRecentCXXRecordDecl())) { - 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(); + PDiag << ft_different_class << QualType(ToMember->getClass(), 0) + << QualType(FromMember->getClass(), 0); return; } FromType = FromMember->getPointeeType(); @@ -3543,13 +3535,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). - CXXRecordDecl *FromClass = FromTypePtr->getMostRecentCXXRecordDecl(); - CXXRecordDecl *ToClass = ToTypePtr->getMostRecentCXXRecordDecl(); + QualType FromClass(FromTypePtr->getClass(), 0); + QualType ToClass(ToTypePtr->getClass(), 0); - if (!declaresSameEntity(FromClass, ToClass) && + if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) { - ConvertedType = Context.getMemberPointerType( - FromTypePtr->getPointeeType(), FromTypePtr->getQualifier(), ToClass); + ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), + ToClass.getTypePtr()); return true; } @@ -3580,23 +3572,10 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( ToPtrType->getPointeeType())) return MemberPointerConversionResult::DifferentPointee; - 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 FromClass = QualType(FromPtrType->getClass(), 0), + ToClass = QualType(ToPtrType->getClass(), 0); - CXXRecordDecl *Base = FromClass, *Derived = ToClass; + QualType Base = FromClass, Derived = ToClass; if (Direction == MemberPointerConversionDirection::Upcast) std::swap(Base, Derived); @@ -3605,19 +3584,16 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths)) return MemberPointerConversionResult::NotDerived; - 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); + if (Paths.isAmbiguous(Base->getCanonicalTypeUnqualified())) { + Diag(CheckLoc, diag::err_ambiguous_memptr_conv) + << int(Direction) << FromClass << ToClass + << getAmbiguousPathsDisplayString(Paths) << OpRange; return MemberPointerConversionResult::Ambiguous; } if (const RecordType *VBase = Paths.getDetectedVirtual()) { - PartialDiagnostic PD = PDiag(diag::err_memptr_conv_via_virtual); - DiagFromTo(PD) << QualType(VBase, 0) << OpRange; - Diag(CheckLoc, PD); + Diag(CheckLoc, diag::err_memptr_conv_via_virtual) + << FromClass << ToClass << QualType(VBase, 0) << OpRange; return MemberPointerConversionResult::Virtual; } @@ -3632,15 +3608,7 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( CheckLoc, Base, Derived, Paths.front(), Direction == MemberPointerConversionDirection::Upcast ? diag::err_upcast_to_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); - })) { + : diag::err_downcast_from_inaccessible_base)) { case Sema::AR_accessible: case Sema::AR_delayed: case Sema::AR_dependent: @@ -8759,7 +8727,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( // and those shouldn't have qualifier variants anyway. if (PointeeTy->isArrayType()) return true; - CXXRecordDecl *Cls = PointerTy->getMostRecentCXXRecordDecl(); + const Type *ClassTy = PointerTy->getClass(); // Iterate through all strict supersets of the pointee type's CVR // qualifiers. @@ -8769,7 +8737,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); MemberPointerTypes.insert( - Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls)); + Context.getMemberPointerType(QPointeeTy, ClassTy)); } return true; @@ -16478,17 +16446,16 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, assert(isa<DeclRefExpr>(SubExpr.get()) && "fixed to something other than a decl ref"); - NestedNameSpecifier *Qualifier = - cast<DeclRefExpr>(SubExpr.get())->getQualifier(); - assert(Qualifier && + assert(cast<DeclRefExpr>(SubExpr.get())->getQualifier() && "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 MemPtrType = Context.getMemberPointerType( - Fn->getType(), Qualifier, - cast<CXXRecordDecl>(Method->getDeclContext())); + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); + QualType MemPtrType + = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); // 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 45fb9d0..c3c993d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5923,12 +5923,8 @@ bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType( } bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType( - const MemberPointerType *T) { - if (Visit(T->getPointeeType())) - return true; - if (auto *RD = T->getMostRecentCXXRecordDecl()) - return VisitTagDecl(RD); - return VisitNestedNameSpecifier(T->getQualifier()); + const MemberPointerType* T) { + return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0)); } bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType( diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index c3bec6b..e6ec4a7 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2127,19 +2127,9 @@ 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, P, A, Info, Deduced, SubTDF, + S, TemplateParams, QualType(MPP->getClass(), 0), + QualType(MPA->getClass(), 0), Info, Deduced, SubTDF, degradeCallPartialOrderingKind(POK), /*DeducedFromArrayBound=*/false, HasDeducedAnyParam); } @@ -4221,8 +4211,8 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, if (!R.HasFormOfMemberPointer) return {}; - return S.Context.getMemberPointerType( - Fn->getType(), /*Qualifier=*/nullptr, Method->getParent()); + return S.Context.getMemberPointerType(Fn->getType(), + S.Context.getTypeDeclType(Method->getParent()).getTypePtr()); } if (!R.IsAddressOfOperand) return Fn->getType(); @@ -6843,8 +6833,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr()); MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced, Depth, Used); - MarkUsedTemplateParameters(Ctx, - QualType(MemPtr->getQualifier()->getAsType(), 0), + MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0), OnlyDeduced, Depth, Used); break; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 3971738..11943c0 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->getQualifier()->isDependent()) + if (!MPTy->getClass()->isDependentType()) (void)isCompleteType(Loc, T); } else { @@ -2685,9 +2685,8 @@ QualType Sema::BuildFunctionType(QualType T, return Context.getFunctionType(T, ParamTypes, EPI); } -QualType Sema::BuildMemberPointerType(QualType T, - NestedNameSpecifier *Qualifier, - CXXRecordDecl *Cls, SourceLocation Loc, +QualType Sema::BuildMemberPointerType(QualType T, QualType Class, + SourceLocation Loc, DeclarationName Entity) { // Verify that we're not building a pointer to pointer to function with // exception specification. @@ -2710,6 +2709,11 @@ QualType Sema::BuildMemberPointerType(QualType T, 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())) { @@ -2730,7 +2734,7 @@ QualType Sema::BuildMemberPointerType(QualType T, if (T->isFunctionType()) adjustMemberFunctionCC(T, /*HasThisPointer=*/true, IsCtorOrDtor, Loc); - return Context.getMemberPointerType(T, Qualifier, Cls); + return Context.getMemberPointerType(T, Class.getTypePtr()); } QualType Sema::BuildBlockPointerType(QualType T, @@ -5334,6 +5338,7 @@ 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, @@ -5343,23 +5348,57 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (SS.isInvalid()) { // Avoid emitting extra errors if we already errored on the scope. D.setInvalidType(true); - 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 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; + } } 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); - AreDeclaratorChunksValid = false; - // FIXME: Maybe we could model these as as a MemberPointerType with a - // non-dependent, non-class qualifier anyway. } + if (!ClsType.isNull()) + T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, + D.getIdentifier()); + else + AreDeclaratorChunksValid = false; + if (T.isNull()) { T = Context.IntTy; D.setInvalidType(true); @@ -6145,8 +6184,48 @@ 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.setQualifierLoc(Chunk.Mem.Scope().getWithLocInContext(Context)); + TL.setClassTInfo(ClsTInfo); } void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Reference); @@ -6975,8 +7054,7 @@ namespace { case MemberPointer: { const MemberPointerType *OldMPT = cast<MemberPointerType>(Old); QualType New = wrap(C, OldMPT->getPointeeType(), I); - return C.getMemberPointerType(New, OldMPT->getQualifier(), - OldMPT->getMostRecentCXXRecordDecl()); + return C.getMemberPointerType(New, OldMPT->getClass()); } case Reference: { @@ -9255,17 +9333,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->getQualifier()->isDependent()) { - QualType T = Context.getTypeDeclType(MPTy->getMostRecentCXXRecordDecl()); + if (!MPTy->getClass()->isDependentType()) { if (getLangOpts().CompleteMemberPointers && - !MPTy->getMostRecentCXXRecordDecl()->isBeingDefined() && - RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete)) + !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() && + RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 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, T); + (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0)); assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl()); } } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5686b9d..b5de98e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -859,13 +859,12 @@ public: SourceLocation Sigil); /// Build a new member pointer type given the pointee type and the - /// qualifier it refers into. + /// class type 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, - NestedNameSpecifier *Qualifier, - CXXRecordDecl *Cls, SourceLocation Sigil); + QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, + SourceLocation Sigil); QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc, @@ -5608,30 +5607,31 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); - const MemberPointerType *T = TL.getTypePtr(); - - NestedNameSpecifierLoc OldQualifierLoc = TL.getQualifierLoc(); - NestedNameSpecifierLoc NewQualifierLoc = - getDerived().TransformNestedNameSpecifierLoc(OldQualifierLoc); - if (!NewQualifierLoc) - return QualType(); + TypeSourceInfo* OldClsTInfo = TL.getClassTInfo(); + TypeSourceInfo *NewClsTInfo = nullptr; + if (OldClsTInfo) { + NewClsTInfo = getDerived().TransformType(OldClsTInfo); + if (!NewClsTInfo) + return QualType(); + } - CXXRecordDecl *OldCls = T->getMostRecentCXXRecordDecl(), *NewCls = nullptr; - if (OldCls) { - NewCls = cast_or_null<CXXRecordDecl>( - getDerived().TransformDecl(TL.getStarLoc(), OldCls)); - if (!NewCls) + 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()) return QualType(); } QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() || - NewQualifierLoc.getNestedNameSpecifier() != - OldQualifierLoc.getNestedNameSpecifier() || - NewCls != OldCls) { - Result = getDerived().RebuildMemberPointerType( - PointeeType, NewQualifierLoc.getNestedNameSpecifier(), NewCls, - TL.getStarLoc()); + if (getDerived().AlwaysRebuild() || + PointeeType != T->getPointeeType() || + NewClsType != OldClsType) { + Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType, + 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.setQualifierLoc(NewQualifierLoc); + NewTL.setClassTInfo(NewClsTInfo); return Result; } @@ -17040,11 +17040,12 @@ TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType, Sigil, getDerived().getBaseEntity()); } -template <typename Derived> -QualType TreeTransform<Derived>::RebuildMemberPointerType( - QualType PointeeType, NestedNameSpecifier *Qualifier, CXXRecordDecl *Cls, - SourceLocation Sigil) { - return SemaRef.BuildMemberPointerType(PointeeType, Qualifier, Cls, Sigil, +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, + QualType ClassType, + SourceLocation Sigil) { + return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil, getDerived().getBaseEntity()); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e53a30c..2b03446 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.setQualifierLoc(ReadNestedNameSpecifierLoc()); + TL.setClassTInfo(GetTypeSourceInfo()); } void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1ffa17d..9e6da4d 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.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); + Record.AddTypeSourceInfo(TL.getClassTInfo()); } void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { diff --git a/clang/lib/Serialization/TemplateArgumentHasher.cpp b/clang/lib/Serialization/TemplateArgumentHasher.cpp index 3c7177b..598f098 100644 --- a/clang/lib/Serialization/TemplateArgumentHasher.cpp +++ b/clang/lib/Serialization/TemplateArgumentHasher.cpp @@ -317,9 +317,7 @@ public: void VisitMemberPointerType(const MemberPointerType *T) { AddQualType(T->getPointeeType()); - AddType(T->getQualifier()->getAsType()); - if (auto *RD = T->getMostRecentCXXRecordDecl()) - AddDecl(RD->getCanonicalDecl()); + AddType(T->getClass()); } void VisitPackExpansionType(const PackExpansionType *T) { |