Make the ".*" operator work correctly when the base is a prvalue and the field has a non-trivial copy constructor. PR13097.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158578 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5bbf750..3de4b57 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2376,6 +2376,10 @@
if (isa<MemberExpr>(E))
return false;
+ if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
+ if (BO->isPtrMemOp())
+ return false;
+
// - opaque values (all)
if (isa<OpaqueValueExpr>(E))
return false;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 198a9bc..0f79448 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -156,7 +156,11 @@
/// \brief An adjustment to be made to the temporary created when emitting a
/// reference binding, which accesses a particular subobject of that temporary.
struct SubobjectAdjustment {
- enum { DerivedToBaseAdjustment, FieldAdjustment } Kind;
+ enum {
+ DerivedToBaseAdjustment,
+ FieldAdjustment,
+ MemberPointerAdjustment
+ } Kind;
union {
struct {
@@ -165,6 +169,11 @@
} DerivedToBase;
FieldDecl *Field;
+
+ struct {
+ const MemberPointerType *MPT;
+ llvm::Value *Ptr;
+ } Ptr;
};
SubobjectAdjustment(const CastExpr *BasePath,
@@ -178,6 +187,12 @@
: Kind(FieldAdjustment) {
this->Field = Field;
}
+
+ SubobjectAdjustment(const MemberPointerType *MPT, llvm::Value *Ptr)
+ : Kind(MemberPointerAdjustment) {
+ this->Ptr.MPT = MPT;
+ this->Ptr.Ptr = Ptr;
+ }
};
}
@@ -345,6 +360,15 @@
continue;
}
}
+ } else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->isPtrMemOp()) {
+ assert(BO->getLHS()->isRValue());
+ E = BO->getLHS();
+ const MemberPointerType *MPT =
+ BO->getRHS()->getType()->getAs<MemberPointerType>();
+ llvm::Value *Ptr = CGF.EmitScalarExpr(BO->getRHS());
+ Adjustments.push_back(SubobjectAdjustment(MPT, Ptr));
+ }
}
if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
@@ -417,6 +441,11 @@
break;
}
+ case SubobjectAdjustment::MemberPointerAdjustment: {
+ Object = CGF.CGM.getCXXABI().EmitMemberDataPointerAddress(
+ CGF, Object, Adjustment.Ptr.Ptr, Adjustment.Ptr.MPT);
+ break;
+ }
}
}
diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp
index 90024e4..fe69cd5 100644
--- a/test/CodeGenCXX/pointers-to-data-members.cpp
+++ b/test/CodeGenCXX/pointers-to-data-members.cpp
@@ -240,3 +240,17 @@
// CHECK-GLOBAL: @_ZN7PR114871xE = global %"union.PR11487::U" { i64 -1, [8 x i8] zeroinitializer }, align 8
}
+
+namespace PR13097 {
+ struct X { int x; X(const X&); };
+ struct A {
+ int qq;
+ X x;
+ };
+ A f();
+ X g() { return f().*&A::x; }
+ // CHECK: define void @_ZN7PR130971gEv
+ // CHECK: call void @_ZN7PR130971fEv
+ // CHECK-NOT: memcpy
+ // CHECK: call void @_ZN7PR130971XC1ERKS0_
+}