@@ -3548,64 +3548,79 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
35483548 return false;
35493549}
35503550
3551- bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
3552- CastKind &Kind,
3553- CXXCastPath &BasePath,
3554- bool IgnoreBaseAccess) {
3555- QualType FromType = From->getType();
3551+ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
3552+ QualType FromType, const MemberPointerType *ToPtrType, CastKind &Kind,
3553+ CXXCastPath &BasePath, SourceLocation CheckLoc, SourceRange OpRange,
3554+ bool IgnoreBaseAccess, MemberPointerConversionDirection Direction) {
35563555 const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
35573556 if (!FromPtrType) {
35583557 // This must be a null pointer to member pointer conversion
3559- assert(From->isNullPointerConstant(Context,
3560- Expr::NPC_ValueDependentIsNull) &&
3561- "Expr must be null pointer constant!");
35623558 Kind = CK_NullToMemberPointer;
3563- return false;
3559+ return MemberPointerConversionResult::Success;
3560+ }
3561+
3562+ // Lock down the inheritance model right now in MS ABI, whether or not the
3563+ // pointee types are the same.
3564+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
3565+ (void)isCompleteType(CheckLoc, FromType);
3566+ (void)isCompleteType(CheckLoc, QualType(ToPtrType, 0));
35643567 }
35653568
3566- const MemberPointerType *ToPtrType = ToType->getAs<MemberPointerType>();
3567- assert(ToPtrType && "No member pointer cast has a target type "
3568- "that is not a member pointer.");
3569+ // T == T, modulo cv
3570+ if (Direction == MemberPointerConversionDirection::Upcast &&
3571+ !Context.hasSameUnqualifiedType(FromPtrType->getPointeeType(),
3572+ ToPtrType->getPointeeType()))
3573+ return MemberPointerConversionResult::DifferentPointee;
35693574
3570- QualType FromClass = QualType(FromPtrType->getClass(), 0);
3571- QualType ToClass = QualType(ToPtrType->getClass(), 0);
3575+ QualType FromClass = QualType(FromPtrType->getClass(), 0),
3576+ ToClass = QualType(ToPtrType->getClass(), 0);
35723577
3573- // FIXME: What about dependent types?
3574- assert(FromClass->isRecordType() && "Pointer into non-class.");
3575- assert(ToClass->isRecordType() && "Pointer into non-class." );
3578+ QualType Base = FromClass, Derived = ToClass;
3579+ if (Direction == MemberPointerConversionDirection::Upcast)
3580+ std::swap(Base, Derived );
35763581
35773582 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
35783583 /*DetectVirtual=*/true);
3579- bool DerivationOkay =
3580- IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass, Paths);
3581- assert(DerivationOkay &&
3582- "Should not have been called if derivation isn't OK.");
3583- (void)DerivationOkay;
3584-
3585- if (Paths.isAmbiguous(Context.getCanonicalType(FromClass).
3586- getUnqualifiedType())) {
3587- std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
3588- Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv)
3589- << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange();
3590- return true;
3584+ if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths))
3585+ return MemberPointerConversionResult::NotDerived;
3586+
3587+ if (Paths.isAmbiguous(Base->getCanonicalTypeUnqualified())) {
3588+ Diag(CheckLoc, diag::err_ambiguous_memptr_conv)
3589+ << int(Direction) << FromClass << ToClass
3590+ << getAmbiguousPathsDisplayString(Paths) << OpRange;
3591+ return MemberPointerConversionResult::Ambiguous;
35913592 }
35923593
35933594 if (const RecordType *VBase = Paths.getDetectedVirtual()) {
3594- Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual)
3595- << FromClass << ToClass << QualType(VBase, 0)
3596- << From->getSourceRange();
3597- return true;
3595+ Diag(CheckLoc, diag::err_memptr_conv_via_virtual)
3596+ << FromClass << ToClass << QualType(VBase, 0) << OpRange;
3597+ return MemberPointerConversionResult::Virtual;
35983598 }
35993599
3600- if (!IgnoreBaseAccess)
3601- CheckBaseClassAccess(From->getExprLoc(), FromClass, ToClass,
3602- Paths.front(),
3603- diag::err_downcast_from_inaccessible_base);
3604-
36053600 // Must be a base to derived member conversion.
36063601 BuildBasePathArray(Paths, BasePath);
3607- Kind = CK_BaseToDerivedMemberPointer;
3608- return false;
3602+ Kind = Direction == MemberPointerConversionDirection::Upcast
3603+ ? CK_DerivedToBaseMemberPointer
3604+ : CK_BaseToDerivedMemberPointer;
3605+
3606+ if (!IgnoreBaseAccess)
3607+ switch (CheckBaseClassAccess(
3608+ CheckLoc, Base, Derived, Paths.front(),
3609+ Direction == MemberPointerConversionDirection::Upcast
3610+ ? diag::err_upcast_to_inaccessible_base
3611+ : diag::err_downcast_from_inaccessible_base)) {
3612+ case Sema::AR_accessible:
3613+ case Sema::AR_delayed:
3614+ case Sema::AR_dependent:
3615+ // Optimistically assume that the delayed and dependent cases
3616+ // will work out.
3617+ break;
3618+
3619+ case Sema::AR_inaccessible:
3620+ return MemberPointerConversionResult::Inaccessible;
3621+ }
3622+
3623+ return MemberPointerConversionResult::Success;
36093624}
36103625
36113626/// Determine whether the lifetime conversion between the two given
0 commit comments