diff options
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 25 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 29 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/ptr-to-datamember.cpp | 27 |
5 files changed, 70 insertions, 26 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 0b56fa94b79..bfbd6f70bc9 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1379,6 +1379,9 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { return EmitLValue(E->getRHS()); } + if (E->getOpcode() == BinaryOperator::PtrMemD) + return EmitPointerToDataMemberBinaryExpr(E); + // Can only get l-value for binary operator expressions which are a // simple assignment of aggregate type. if (E->getOpcode() != BinaryOperator::Assign) @@ -1560,3 +1563,25 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType, CallingConvention), Callee, Args, TargetDecl); } + +LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr( + const BinaryOperator *E) { + llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress(); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext()); + BaseV = Builder.CreateBitCast(BaseV, i8Ty); + LValue RHSLV = EmitLValue(E->getRHS()); + llvm::Value *OffsetV = + EmitLoadOfLValue(RHSLV, E->getRHS()->getType()).getScalarVal(); + const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType()); + OffsetV = Builder.CreateBitCast(OffsetV, ResultType); + llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr"); + QualType Ty = E->getRHS()->getType(); + const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>(); + Ty = MemPtrType->getPointeeType(); + const llvm::Type* PType = + ConvertType(getContext().getPointerType(Ty)); + AddV = Builder.CreateBitCast(AddV, PType); + LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty)); + return LV; +} + diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 066029f9a53..f47b6ab3c8c 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -92,6 +92,7 @@ public: void VisitCallExpr(const CallExpr *E); void VisitStmtExpr(const StmtExpr *E); void VisitBinaryOperator(const BinaryOperator *BO); + void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO); void VisitBinAssign(const BinaryOperator *E); void VisitBinComma(const BinaryOperator *E); void VisitUnaryAddrOf(const UnaryOperator *E); @@ -328,7 +329,16 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { } void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { - CGF.ErrorUnsupported(E, "aggregate binary expression"); + if (E->getOpcode() == BinaryOperator::PtrMemD) + VisitPointerToDataMemberBinaryOperator(E); + else + CGF.ErrorUnsupported(E, "aggregate binary expression"); +} + +void AggExprEmitter::VisitPointerToDataMemberBinaryOperator( + const BinaryOperator *E) { + LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E); + EmitFinalDestCopy(E, LV); } void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 831b48033a7..69604f9aaae 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -106,7 +106,6 @@ public: return 0; } Value *VisitExpr(Expr *S); - Value *VisitPointerToDataMemberBinaryExpr(const BinaryOperator *BExpr); Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); } @@ -539,8 +538,11 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, Value *ScalarExprEmitter::VisitExpr(Expr *E) { if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E)) - if (BExpr->getOpcode() == BinaryOperator::PtrMemD) - return VisitPointerToDataMemberBinaryExpr(BExpr); + if (BExpr->getOpcode() == BinaryOperator::PtrMemD) { + LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr); + Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal(); + return InVal; + } CGF.ErrorUnsupported(E, "scalar expression"); if (E->getType()->isVoidType()) @@ -548,27 +550,6 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) { return llvm::UndefValue::get(CGF.ConvertType(E->getType())); } -Value *ScalarExprEmitter::VisitPointerToDataMemberBinaryExpr( - const BinaryOperator *E) { - Value *BaseV = EmitLValue(E->getLHS()).getAddress(); - const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - BaseV = Builder.CreateBitCast(BaseV, i8Ty); - Value *OffsetV = EmitLoadOfLValue(E->getRHS()); - const llvm::Type* ResultType = ConvertType( - CGF.getContext().getPointerDiffType()); - OffsetV = Builder.CreateBitCast(OffsetV, ResultType); - Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr"); - QualType Ty = E->getRHS()->getType(); - const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>(); - Ty = MemPtrType->getPointeeType(); - const llvm::Type* PType = - ConvertType(CGF.getContext().getPointerType(Ty)); - AddV = Builder.CreateBitCast(AddV, PType); - LValue LV = LValue::MakeAddr(AddV, CGF.MakeQualifiers(Ty)); - Value *InVal = CGF.EmitLoadOfLValue(LV, Ty).getScalarVal(); - return InVal; -} - Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { llvm::SmallVector<llvm::Constant*, 32> indices; for (unsigned i = 2; i < E->getNumSubExprs(); i++) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3e65e47024b..639e683f036 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -845,7 +845,8 @@ public: LValue EmitObjCKVCRefLValue(const ObjCImplicitSetterGetterRefExpr *E); LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E); LValue EmitStmtExprLValue(const StmtExpr *E); - + LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E); + //===--------------------------------------------------------------------===// // Scalar Expression Emission //===--------------------------------------------------------------------===// diff --git a/clang/test/CodeGenCXX/ptr-to-datamember.cpp b/clang/test/CodeGenCXX/ptr-to-datamember.cpp index b0d7ddc7796..eee03c060f9 100644 --- a/clang/test/CodeGenCXX/ptr-to-datamember.cpp +++ b/clang/test/CodeGenCXX/ptr-to-datamember.cpp @@ -2,6 +2,12 @@ extern "C" int printf(...); +struct F { + F() : iF(1), fF(2.0) {} + int iF; + float fF; +}; + struct V { double d; int iV; @@ -23,8 +29,28 @@ public: float f; double d; int Ai; + F Af; }; +void pr(const F& b) { + printf(" %d %f\n", b.iF, b.fF); +} + +void test_aggr_pdata(A& a1) { + F A::* af = &A::Af; + pr(a1.*af); + + (a1.*af).iF = 100; + (a1.*af).fF = 200.00; + printf(" %d %f\n", (a1.*af).iF, (a1.*af).fF); + pr(a1.*af); + + (a1.*af).iF++; + (a1.*af).fF--; + --(a1.*af).fF; + pr(a1.*af); +} + int main() { A a1; @@ -40,4 +66,5 @@ int main() printf("%d\n", &A::B::V::iV); printf("%d\n", &A::B1::V::iV); printf("%d, %f, %f \n", a1.*pa, a1.*pf, a1.*pd); + test_aggr_pdata(a1); } |