diff options
| author | Eli Friedman <eli.friedman@gmail.com> | 2009-11-27 04:41:50 +0000 |
|---|---|---|
| committer | Eli Friedman <eli.friedman@gmail.com> | 2009-11-27 04:41:50 +0000 |
| commit | e96f1d3b2f98304820e5502f2cdda353b393980b (patch) | |
| tree | 902019b867fccac2937fc8aeb7871108e344c9c5 /clang/lib | |
| parent | 0dfc6804ff300df1efc7092ed624abe718a20d53 (diff) | |
| download | bcm5719-llvm-e96f1d3b2f98304820e5502f2cdda353b393980b.tar.gz bcm5719-llvm-e96f1d3b2f98304820e5502f2cdda353b393980b.zip | |
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.
llvm-svn: 89987
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 40 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 26 |
2 files changed, 47 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 53d45b71258..120db43d44f 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/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<CXXDynamicCastExpr>(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<CXXRecordDecl>(E->getType()->getAs<MemberPointerType>()-> + getClass()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *DerivedDecl = + cast<CXXRecordDecl>(CE->getType()->getAs<MemberPointerType>()-> + getClass()->getAs<RecordType>()->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<MemberPointerType>(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index af7a56fb7b0..0b3426b2f3c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1141,21 +1141,25 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (CastArg.isInvalid()) return true; - + + From = CastArg.takeAs<Expr>(); + + // 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<Expr>(); 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<Expr>(), - 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: |

