Skip to content
Snippets Groups Projects
Commit b6defdfa authored by John McCall's avatar John McCall
Browse files

Collect SEH captures in a set instead of a vector to avoid

doing redundant work if a variable is used multiple times.

Fixes PR24751.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247075 91177308-0d34-0410-b5e6-96231b3b80d8
parent fe51609c
No related branches found
No related tags found
No related merge requests found
......@@ -1433,7 +1433,7 @@ namespace {
struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
CodeGenFunction &ParentCGF;
const VarDecl *ParentThis;
SmallVector<const VarDecl *, 4> Captures;
llvm::SmallSetVector<const VarDecl *, 4> Captures;
Address SEHCodeSlot = Address::invalid();
CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
: ParentCGF(ParentCGF), ParentThis(ParentThis) {}
......@@ -1454,17 +1454,17 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
void VisitDeclRefExpr(const DeclRefExpr *E) {
// If this is already a capture, just make sure we capture 'this'.
if (E->refersToEnclosingVariableOrCapture()) {
Captures.push_back(ParentThis);
Captures.insert(ParentThis);
return;
}
const auto *D = dyn_cast<VarDecl>(E->getDecl());
if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
Captures.push_back(D);
Captures.insert(D);
}
void VisitCXXThisExpr(const CXXThisExpr *E) {
Captures.push_back(ParentThis);
Captures.insert(ParentThis);
}
void VisitCallExpr(const CallExpr *E) {
......
......@@ -230,4 +230,34 @@ int except_return(void) {
// CHECK: %[[r:[^ ]*]] = load i32, i32* %[[rv]]
// CHECK: ret i32 %[[r]]
// PR 24751: don't assert if a variable is used twice in a __finally block.
// Also, make sure we don't do redundant work to capture/project it.
void finally_capture_twice(int x) {
__try {
} __finally {
int y = x;
int z = x;
}
}
//
// CHECK-LABEL: define void @finally_capture_twice(
// CHECK: [[X:%.*]] = alloca i32, align 4
// CHECK: call void (...) @llvm.localescape(i32* [[X]])
// CHECK-NEXT: store i32 {{.*}}, i32* [[X]], align 4
// CHECK-NEXT: [[LOCAL:%.*]] = call i8* @llvm.localaddress()
// CHECK-NEXT: call void [[FINALLY:@.*]](i8{{ zeroext | }}0, i8* [[LOCAL]])
// CHECK: define internal void [[FINALLY]](
// CHECK: [[LOCAL:%.*]] = call i8* @llvm.localrecover(
// CHECK: [[X:%.*]] = bitcast i8* [[LOCAL]] to i32*
// CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i8*
// CHECK-NEXT: store i8
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]], align 4
// CHECK-NEXT: store i32 [[T0]], i32* [[Y]], align 4
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]], align 4
// CHECK-NEXT: store i32 [[T0]], i32* [[Z]], align 4
// CHECK-NEXT: ret void
// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment