From: Eli Friedman Date: Fri, 27 Nov 2009 04:41:50 +0000 (+0000) Subject: More work on ScalarExprEmitter::EmitCastExpr: for every cast kind, either X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d888962cff03b543fbe9ac6051ec6addf5b993b4;p=clang More work on ScalarExprEmitter::EmitCastExpr: for every cast kind, either implement it explicitly or assert that it doesn't make sense for a scalar. This caught a couple interesting issues: one, CK_BaseToDerivedMemberPointer casts were getting silently miscompiled, and two, Sema was constructing some strange implicit casts of type CK_UserDefinedConversion. The change in SemaExprCXX makes sure the cast kinds are getting set correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89987 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 53d45b7125..120db43d44 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -187,14 +187,14 @@ public: Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return llvm::Constant::getNullValue(ConvertType(E->getType())); } - Value *VisitCastExpr(const CastExpr *E) { + Value *VisitCastExpr(CastExpr *E) { // Make sure to evaluate VLA bounds now so that we have them for later. if (E->getType()->isVariablyModifiedType()) CGF.EmitVLASize(E->getType()); return EmitCastExpr(E); } - Value *EmitCastExpr(const CastExpr *E); + Value *EmitCastExpr(CastExpr *E); Value *VisitCallExpr(const CallExpr *E) { if (E->getCallReturnType()->isReferenceType()) @@ -782,8 +782,8 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) { // VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts // have to handle a more broad range of conversions than explicit casts, as they // handle things like function to ptr-to-function decay etc. -Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { - const Expr *E = CE->getSubExpr(); +Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { + Expr *E = CE->getSubExpr(); QualType DestTy = CE->getType(); CastExpr::CastKind Kind = CE->getCastKind(); @@ -795,6 +795,7 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { // are in the same order as in the CastKind enum. switch (Kind) { case CastExpr::CK_Unknown: + // FIXME: All casts should have a known kind! //assert(0 && "Unknown cast kind!"); break; @@ -838,10 +839,10 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { const CXXDynamicCastExpr *DCE = cast(CE); return CGF.EmitDynamicCast(V, DCE); } - case CastExpr::CK_ToUnion: { + case CastExpr::CK_ToUnion: assert(0 && "Should be unreachable!"); break; - } + case CastExpr::CK_ArrayToPointerDecay: { assert(E->getType()->isArrayType() && "Array to pointer decay must have array source type!"); @@ -867,9 +868,32 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { return CGF.CGM.EmitNullConstant(DestTy); case CastExpr::CK_BaseToDerivedMemberPointer: - case CastExpr::CK_DerivedToBaseMemberPointer: + case CastExpr::CK_DerivedToBaseMemberPointer: { + Value *Src = Visit(E); + + // See if we need to adjust the pointer. + const CXXRecordDecl *BaseDecl = + cast(E->getType()->getAs()-> + getClass()->getAs()->getDecl()); + const CXXRecordDecl *DerivedDecl = + cast(CE->getType()->getAs()-> + getClass()->getAs()->getDecl()); + if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer) + std::swap(DerivedDecl, BaseDecl); + + llvm::Constant *Adj = CGF.CGM.GetCXXBaseClassOffset(DerivedDecl, BaseDecl); + if (Adj) { + if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer) + Src = Builder.CreateSub(Src, Adj, "adj"); + else + Src = Builder.CreateAdd(Src, Adj, "adj"); + } + return Src; + } + case CastExpr::CK_UserDefinedConversion: case CastExpr::CK_ConstructorConversion: + assert(0 && "Should be unreachable!"); break; case CastExpr::CK_IntegralToPointer: { @@ -918,7 +942,7 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { case CastExpr::CK_IntegralToFloating: case CastExpr::CK_FloatingToIntegral: case CastExpr::CK_FloatingCast: - break; + return EmitScalarConversion(Visit(E), E->getType(), DestTy); case CastExpr::CK_MemberPointerToBoolean: { const MemberPointerType* T = E->getType()->getAs(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index af7a56fb7b..0b3426b2f3 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1141,21 +1141,25 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (CastArg.isInvalid()) return true; - + + From = CastArg.takeAs(); + + // FIXME: This and the following if statement shouldn't be necessary, but + // there's some nasty stuff involving MaybeBindToTemporary going on here. if (ICS.UserDefined.After.Second == ICK_Derived_To_Base && ICS.UserDefined.After.CopyConstructor) { - From = CastArg.takeAs(); return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor); } - - if (ICS.UserDefined.After.Second == ICK_Pointer_Member && - ToType.getNonReferenceType()->isMemberFunctionPointerType()) - CastKind = CastExpr::CK_BaseToDerivedMemberPointer; - - From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(), - CastKind, CastArg.takeAs(), - ToType->isLValueReferenceType()); - return false; + + if (ICS.UserDefined.After.CopyConstructor) { + From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(), + CastKind, From, + ToType->isLValueReferenceType()); + return false; + } + + return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, + "converting", IgnoreBaseAccess); } case ImplicitConversionSequence::EllipsisConversion: