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:
John McCall 2010-11-17 00:07:33 +00:00
Родитель 34c26300b3
Коммит 74fb0edb44
3 изменённых файлов: 42 добавлений и 4 удалений

Просмотреть файл

@ -394,8 +394,8 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
CGF.BeginConditionalBranch(); CGF.BeginConditionalBranch();
CGF.EmitBlock(LHSBlock); CGF.EmitBlock(LHSBlock);
// Handle the GNU extension for missing LHS. // Save whether the destination's lifetime is externally managed.
assert(E->getLHS() && "Must have LHS for aggregate value"); bool DestLifetimeManaged = Dest.isLifetimeExternallyManaged();
Visit(E->getLHS()); Visit(E->getLHS());
CGF.EndConditionalBranch(); CGF.EndConditionalBranch();
@ -404,6 +404,12 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
CGF.BeginConditionalBranch(); CGF.BeginConditionalBranch();
CGF.EmitBlock(RHSBlock); 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()); Visit(E->getRHS());
CGF.EndConditionalBranch(); CGF.EndConditionalBranch();
CGF.EmitBranch(ContBlock); CGF.EmitBranch(ContBlock);

Просмотреть файл

@ -379,8 +379,8 @@ public:
bool isLifetimeExternallyManaged() const { bool isLifetimeExternallyManaged() const {
return LifetimeFlag; return LifetimeFlag;
} }
void setLifetimeExternallyManaged() { void setLifetimeExternallyManaged(bool Managed = true) {
LifetimeFlag = true; LifetimeFlag = Managed;
} }
bool isVolatile() const { bool isVolatile() const {

Просмотреть файл

@ -493,3 +493,35 @@ namespace Elision {
A(*x).foo(); 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);
}
}