зеркало из https://github.com/microsoft/clang-1.git
Reset the lifetime-managed flag between emission of the agg conditional
branches. Fixes PR8623. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119408 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
34c26300b3
Коммит
74fb0edb44
|
@ -394,8 +394,8 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
|
|||
CGF.BeginConditionalBranch();
|
||||
CGF.EmitBlock(LHSBlock);
|
||||
|
||||
// Handle the GNU extension for missing LHS.
|
||||
assert(E->getLHS() && "Must have LHS for aggregate value");
|
||||
// Save whether the destination's lifetime is externally managed.
|
||||
bool DestLifetimeManaged = Dest.isLifetimeExternallyManaged();
|
||||
|
||||
Visit(E->getLHS());
|
||||
CGF.EndConditionalBranch();
|
||||
|
@ -404,6 +404,12 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
|
|||
CGF.BeginConditionalBranch();
|
||||
CGF.EmitBlock(RHSBlock);
|
||||
|
||||
// If the result of an agg expression is unused, then the emission
|
||||
// of the LHS might need to create a destination slot. That's fine
|
||||
// with us, and we can safely emit the RHS into the same slot, but
|
||||
// we shouldn't claim that its lifetime is externally managed.
|
||||
Dest.setLifetimeExternallyManaged(DestLifetimeManaged);
|
||||
|
||||
Visit(E->getRHS());
|
||||
CGF.EndConditionalBranch();
|
||||
CGF.EmitBranch(ContBlock);
|
||||
|
|
|
@ -379,8 +379,8 @@ public:
|
|||
bool isLifetimeExternallyManaged() const {
|
||||
return LifetimeFlag;
|
||||
}
|
||||
void setLifetimeExternallyManaged() {
|
||||
LifetimeFlag = true;
|
||||
void setLifetimeExternallyManaged(bool Managed = true) {
|
||||
LifetimeFlag = Managed;
|
||||
}
|
||||
|
||||
bool isVolatile() const {
|
||||
|
|
|
@ -493,3 +493,35 @@ namespace Elision {
|
|||
A(*x).foo();
|
||||
}
|
||||
}
|
||||
|
||||
namespace PR8623 {
|
||||
struct A { A(int); ~A(); };
|
||||
|
||||
// CHECK: define void @_ZN6PR86233fooEb(
|
||||
void foo(bool b) {
|
||||
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
|
||||
// CHECK-NEXT: [[LCONS:%.*]] = alloca i1
|
||||
// CHECK-NEXT: [[RCONS:%.*]] = alloca i1
|
||||
// CHECK-NEXT: store i1 false, i1* [[RCONS]]
|
||||
// CHECK-NEXT: store i1 false, i1* [[LCONS]]
|
||||
// CHECK: br i1
|
||||
// CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 2)
|
||||
// CHECK-NEXT: store i1 true, i1* [[LCONS]]
|
||||
// CHECK-NEXT: br label
|
||||
// CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 3)
|
||||
// CHECK-NEXT: store i1 true, i1* [[RCONS]]
|
||||
// CHECK-NEXT: br label
|
||||
// CHECK: load i1* [[RCONS]]
|
||||
// CHECK-NEXT: br i1
|
||||
// CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
|
||||
// CHECK-NEXT: store i1 false, i1* [[RCONS]]
|
||||
// CHECK-NEXT: br label
|
||||
// CHECK: load i1* [[LCONS]]
|
||||
// CHECK-NEXT: br i1
|
||||
// CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
|
||||
// CHECK-NEXT: store i1 false, i1* [[LCONS]]
|
||||
// CHECK-NEXT: br label
|
||||
// CHECK: ret void
|
||||
b ? A(2) : A(3);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче