From 3b477597fa1184b223ad5ad9dfe1c870b8aa1ac5 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 25 Jul 2013 00:23:42 +0000 Subject: [PATCH] Debug Info: Fine-tune the simple return expression location handling to only affect functions without a separate return block. This fixes the linetable for void functions with cleanups and multiple returns. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187090 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenFunction.cpp | 22 ++++++++++------- test/CodeGenCXX/linetable-cleanup.cpp | 34 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 51b86f77e5..addc25f531 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -191,14 +191,20 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { "mismatched push/pop in break/continue stack!"); bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 - && NumSimpleReturnExprs == NumReturnExprs; - // If the function contains only a simple return statement, the - // location before the cleanup code becomes the last useful - // breakpoint in the function, because the simple return expression - // will be evaluated after the cleanup code. To be safe, set the - // debug location for cleanup code to the location of the return - // statement. Otherwise the cleanup code should be at the end of the - // function's lexical scope. + && NumSimpleReturnExprs == NumReturnExprs + && ReturnBlock.getBlock()->use_empty(); + // Usually the return expression is evaluated before the cleanup + // code. If the function contains only a simple return statement, + // such as a constant, the location before the cleanup code becomes + // the last useful breakpoint in the function, because the simple + // return expression will be evaluated after the cleanup code. To be + // safe, set the debug location for cleanup code to the location of + // the return statement. Otherwise the cleanup code should be at the + // end of the function's lexical scope. + // + // If there are multiple branches to the return block, the branch + // instructions will get the location of the return statements and + // all will be fine. if (CGDebugInfo *DI = getDebugInfo()) { if (OnlySimpleReturnStmts) DI->EmitLocation(Builder, LastStopPoint); diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp index 1f117f2afa..96b8572252 100644 --- a/test/CodeGenCXX/linetable-cleanup.cpp +++ b/test/CodeGenCXX/linetable-cleanup.cpp @@ -7,6 +7,12 @@ // CHECK: call void @_ZN1CD1Ev(%class.C* {{.*}}), !dbg ![[CLEANUP:[0-9]+]] // CHECK: ret i32 0, !dbg ![[RET:[0-9]+]] +// CHECK: define {{.*}}bar +// CHECK: ret void, !dbg ![[RETBAR:[0-9]+]] + +// CHECK: define {{.*}}baz +// CHECK: ret void, !dbg ![[RETBAZ:[0-9]+]] + class C { public: ~C() {} @@ -22,3 +28,31 @@ int foo() return 0; // CHECK: ![[RET]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} } + +void bar() +{ + if (!foo()) + // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return; + + if (foo()) { + C c; + c.i = foo(); + } + // Clang creates only a single ret instruction. Make sure it is at a useful line. + // CHECK: ![[RETBAR]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} + +void baz() +{ + if (!foo()) + // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return; + + if (foo()) { + // no cleanup + // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return; + } + // CHECK: ![[RETBAZ]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} -- 2.40.0