diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-03-07 23:24:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-03-07 23:24:59 +0000 |
commit | 4ce46c2db2b17ef52b34dbeeec01e448025c8edc (patch) | |
tree | a81e646a24fd524ac8df5c9f8678cd835514aa1f /lib | |
parent | a1a9f035852e35ed88f4902a855eb952cf08bebb (diff) |
Perform overload resolution when static_cast'ing from a
pointer-to-member-to-derived to a pointer-to-member-to-base. Fixes
PR6072.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97923 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 38 |
2 files changed, 44 insertions, 4 deletions
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index ac189a0649..5af6f91d14 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -178,6 +178,11 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { //===----------------------------------------------------------------------===// void AggExprEmitter::VisitCastExpr(CastExpr *E) { + if (!DestPtr) { + Visit(E->getSubExpr()); + return; + } + switch (E->getCastKind()) { default: assert(0 && "Unhandled cast kind!"); @@ -205,6 +210,11 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { break; case CastExpr::CK_NullToMemberPointer: { + // If the subexpression's type is the C++0x nullptr_t, emit the + // subexpression, which may have side effects. + if (E->getSubExpr()->getType()->isNullPtrType()) + Visit(E->getSubExpr()); + const llvm::Type *PtrDiffTy = CGF.ConvertType(CGF.getContext().getPointerDiffType()); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 0097cd363c..e04abd2aac 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -84,7 +84,8 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, CastExpr::CastKind &Kind); -static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, +static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, + QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -554,7 +555,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // Reverse member pointer conversion. C++ 4.11 specifies member pointer // conversion. C++ 5.2.9p9 has additional information. // DR54's access restrictions apply here also. - tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle, + tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle, OpRange, msg, Kind); if (tcr != TC_NotApplicable) return tcr; @@ -798,12 +799,23 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, /// where B is a base class of D [...]. /// TryCastResult -TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, - bool CStyle, const SourceRange &OpRange, +TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, + QualType DestType, bool CStyle, + const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind) { const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(); if (!DestMemPtr) return TC_NotApplicable; + + bool WasOverloadedFunction = false; + if (FunctionDecl *Fn + = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false)) { + CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); + SrcType = Self.Context.getMemberPointerType(Fn->getType(), + Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); + WasOverloadedFunction = true; + } + const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>(); if (!SrcMemPtr) { msg = diag::err_bad_static_cast_member_pointer_nonmp; @@ -853,6 +865,24 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, return TC_Failed; } + if (WasOverloadedFunction) { + // Resolve the address of the overloaded function again, this time + // allowing complaints if something goes wrong. + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr, + DestType, + true); + if (!Fn) { + msg = 0; + return TC_Failed; + } + + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, Fn); + if (!SrcExpr) { + msg = 0; + return TC_Failed; + } + } + Kind = CastExpr::CK_DerivedToBaseMemberPointer; return TC_Success; } |