Make the ".*" operator work correctly when the base is a prvalue and the field has a non-trivial copy constructor. PR13097.

llvm-svn: 158578
This commit is contained in:
Eli Friedman 2012-06-15 23:51:06 +00:00
parent 38a6fbf933
commit 13ffdd86b9
3 changed files with 48 additions and 1 deletions

View File

@ -2376,6 +2376,10 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const {
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;

View File

@ -156,7 +156,11 @@ namespace {
/// \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 @@ namespace {
} DerivedToBase;
FieldDecl *Field;
struct {
const MemberPointerType *MPT;
llvm::Value *Ptr;
} Ptr;
};
SubobjectAdjustment(const CastExpr *BasePath,
@ -178,6 +187,12 @@ namespace {
: 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 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
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 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
break;
}
case SubobjectAdjustment::MemberPointerAdjustment: {
Object = CGF.CGM.getCXXABI().EmitMemberDataPointerAddress(
CGF, Object, Adjustment.Ptr.Ptr, Adjustment.Ptr.MPT);
break;
}
}
}

View File

@ -240,3 +240,17 @@ namespace PR11487 {
// 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_
}