From: David Majnemer Date: Tue, 1 Mar 2016 19:42:53 +0000 (+0000) Subject: [MSVC Compat] Correctly handle finallys nested within finallys X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7cd5e16c007698b4f41784e154d445b780d83f12;p=clang [MSVC Compat] Correctly handle finallys nested within finallys We'd lose track of the parent CodeGenFunction, leading us to get confused with regard to which function a nested finally belonged to. Differential Revision: http://reviews.llvm.org/D17752 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262379 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index bf52152237..3c73000832 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -1625,14 +1625,13 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, SmallString<128> Name; { llvm::raw_svector_ostream OS(Name); - const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl; - const NamedDecl *Parent = dyn_cast_or_null(ParentCodeDecl); - assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH"); + const FunctionDecl *ParentSEHFn = ParentCGF.CurSEHParent; + assert(ParentSEHFn && "No CurSEHParent!"); MangleContext &Mangler = CGM.getCXXABI().getMangleContext(); if (IsFilter) - Mangler.mangleSEHFilterExpression(Parent, OS); + Mangler.mangleSEHFilterExpression(ParentSEHFn, OS); else - Mangler.mangleSEHFinallyBlock(Parent, OS); + Mangler.mangleSEHFinallyBlock(ParentSEHFn, OS); } FunctionArgList Args; @@ -1679,6 +1678,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args, OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart()); + CurSEHParent = ParentCGF.CurSEHParent; CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 8e327c2bc4..0e118b8f6f 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -669,6 +669,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, DidCallStackSave = false; CurCodeDecl = D; + if (const auto *FD = dyn_cast_or_null(D)) + if (FD->usesSEHTry()) + CurSEHParent = FD; CurFuncDecl = (D ? D->getNonClosureContext() : nullptr); FnRetTy = RetTy; CurFn = Fn; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 9a31c8f78b..b9421fc012 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -276,6 +276,8 @@ public: /// potentially set the return value. bool SawAsmBlock; + const FunctionDecl *CurSEHParent = nullptr; + /// True if the current function is an outlined SEH helper. This can be a /// finally block or filter expression. bool IsOutlinedSEHHelper; @@ -1150,10 +1152,7 @@ public: return getInvokeDestImpl(); } - bool currentFunctionUsesSEHTry() const { - const auto *FD = dyn_cast_or_null(CurCodeDecl); - return FD && FD->usesSEHTry(); - } + bool currentFunctionUsesSEHTry() const { return CurSEHParent != nullptr; } const TargetInfo &getTarget() const { return Target; } llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); } diff --git a/test/CodeGen/exceptions-seh-finally.c b/test/CodeGen/exceptions-seh-finally.c index f0ed223064..be1501f9e9 100644 --- a/test/CodeGen/exceptions-seh-finally.c +++ b/test/CodeGen/exceptions-seh-finally.c @@ -230,3 +230,28 @@ int nested___finally___finally_with_eh_edge() { // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) // CHECK: unreachable + +void finally_within_finally() { + __try { + might_crash(); + } __finally { + __try { + might_crash(); + } __finally { + } + } +} + +// CHECK-LABEL: define void @finally_within_finally( +// CHECK: invoke void @might_crash( + +// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"( +// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"( + +// CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"( +// CHECK: invoke void @might_crash( + +// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"( +// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"( + +// CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"(