diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 22 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/linetable-cleanup.cpp | 34 |
2 files changed, 48 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 51b86f77e59..addc25f5310 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/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/clang/test/CodeGenCXX/linetable-cleanup.cpp b/clang/test/CodeGenCXX/linetable-cleanup.cpp index 1f117f2afa5..96b85722526 100644 --- a/clang/test/CodeGenCXX/linetable-cleanup.cpp +++ b/clang/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} +} |