diff options
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 20 | ||||
-rw-r--r-- | test/CodeGenObjC/object-incr-decr-1.m | 19 |
2 files changed, 38 insertions, 1 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 0316116631..8103506c2f 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -690,7 +690,25 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, llvm::Constant *Inc = VMContext.getConstantInt(llvm::Type::Int32Ty, AmountVal); if (!isa<llvm::FunctionType>(PT->getElementType())) { - NextVal = Builder.CreateGEP(InVal, Inc, "ptrincdec"); + QualType PTEE = ValTy->getPointeeType(); + if (const ObjCInterfaceType *OIT = + dyn_cast<ObjCInterfaceType>(PTEE)) { + // Handle interface types, which are not represented with a concrete type. + int size = CGF.getContext().getTypeSize(OIT) / 8; + if (!isInc) + size = -size; + Inc = VMContext.getConstantInt(Inc->getType(), size); + const llvm::Type *i8Ty = + VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty); + InVal = Builder.CreateBitCast(InVal, i8Ty); + NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr"); + llvm::Value *lhs = LV.getAddress(); + lhs = Builder.CreateBitCast(lhs, VMContext.getPointerTypeUnqual(i8Ty)); + LV = LValue::MakeAddr(lhs, ValTy.getCVRQualifiers(), + CGF.getContext().getObjCGCAttrKind(ValTy)); + } + else + NextVal = Builder.CreateGEP(InVal, Inc, "ptrincdec"); } else { const llvm::Type *i8Ty = VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty); diff --git a/test/CodeGenObjC/object-incr-decr-1.m b/test/CodeGenObjC/object-incr-decr-1.m new file mode 100644 index 0000000000..96c218215d --- /dev/null +++ b/test/CodeGenObjC/object-incr-decr-1.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -emit-llvm %s + +@interface Foo +{ + double d1,d3,d4; +} +@end + +Foo* foo() +{ + Foo *f; + + // Both of these crash clang nicely + ++f; + --f; + f--; + f++; + return f; +} |