diff options
author | Matheus Izvekov <mizvekov@gmail.com> | 2025-03-20 11:09:25 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-20 11:09:25 -0300 |
commit | 6cd62ad08c974b7d4f7171c66f6567de82bd236f (patch) | |
tree | 259dbf4169ef28a26ddb2663b12beffb51ff789b /clang/lib/Sema | |
parent | e6a87da8fe314a009eed769f9737b4b281a06fba (diff) | |
download | llvm-6cd62ad08c974b7d4f7171c66f6567de82bd236f.zip llvm-6cd62ad08c974b7d4f7171c66f6567de82bd236f.tar.gz llvm-6cd62ad08c974b7d4f7171c66f6567de82bd236f.tar.bz2 |
Revert "[clang] improve class type sugar preservation in pointers to members" (#132215)
Reverts llvm/llvm-project#130537
This missed updating lldb, which we didn't notice due to lack of
pre-commit CI.
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 87 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 122 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 59 |
10 files changed, 184 insertions, 162 deletions
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 90a4a5a..f085fac 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7368,7 +7368,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) @@ -7379,8 +7378,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 670c27f..161c0da 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; @@ -16463,17 +16431,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()); } |