forked from OSchip/llvm-project
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:
parent
38a6fbf933
commit
13ffdd86b9
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue