diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index 861d31fb7fc960d1aa006307c908bdbbcef22406..ba6b56c2676fafeecaafdeffa6659d6dd5cb96b0 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -371,7 +371,8 @@ void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) { } /// Pops cleanup blocks until the given savepoint is reached. -void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) { +void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old, + SourceLocation EHLoc) { assert(Old.isValid()); while (EHStack.stable_begin() != Old) { @@ -383,7 +384,7 @@ void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) { bool FallThroughIsBranchThrough = Old.strictlyEncloses(Scope.getEnclosingNormalCleanup()); - PopCleanupBlock(FallThroughIsBranchThrough); + PopCleanupBlock(FallThroughIsBranchThrough, EHLoc); } } @@ -532,7 +533,8 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF, /// Pops a cleanup block. If the block includes a normal cleanup, the /// current insertion point is threaded through the cleanup, as are /// any branch fixups on the cleanup. -void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { +void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough, + SourceLocation EHLoc) { assert(!EHStack.empty() && "cleanup stack is empty!"); assert(isa(*EHStack.begin()) && "top not a cleanup!"); EHCleanupScope &Scope = cast(*EHStack.begin()); @@ -833,6 +835,9 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // Emit the EH cleanup if required. if (RequiresEHCleanup) { + if (CGDebugInfo *DI = getDebugInfo()) + DI->EmitLocation(Builder, EHLoc); + CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); EmitBlock(EHEntry); @@ -840,6 +845,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // We only actually emit the cleanup code if the cleanup is either // active or was used before it was deactivated. if (EHActiveFlag || IsActive) { + cleanupFlags.setIsForEHCleanup(); EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 73f66e0c8c7dea12c4e6b248d902cf090012434f..5e2ebe0d9cd4656e9278c6a172513dc09ed0d77f 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -38,8 +38,8 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) { Loc = S->getLocStart(); DI->EmitLocation(Builder, Loc); - if (++NumStopPoints == 1) - FirstStopPoint = Loc; + //if (++NumStopPoints == 1) + LastStopPoint = Loc; } } @@ -842,8 +842,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { } } + NumReturnExprs += 1; if (RV == 0 || RV->isEvaluatable(getContext())) - ++NumSimpleReturnExprs; + NumSimpleReturnExprs += 1; cleanupScope.ForceCleanup(); EmitBranchThroughCleanup(ReturnBlock); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 122e95b2663256ec8a4be6e1a4d1495d5359f60f..9f97560600548a9e7919865267e3417210e283ec 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -44,7 +44,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0), DidCallStackSave(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), - NumStopPoints(0), NumSimpleReturnExprs(0), + NumReturnExprs(0), NumSimpleReturnExprs(0), CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXDefaultInitExprThis(0), CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0), @@ -188,14 +188,14 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { assert(BreakContinueStack.empty() && "mismatched push/pop in break/continue stack!"); - // If the function contains only a single, simple return statement, - // the cleanup code may become the first breakpoint in the - // function. To be safe set the debug location for it to the - // location of the return statement. Otherwise point it to end of - // the function's lexical scope. + // If the function contains only a simple return statement, the + // cleanup code may become the first breakpoint in the function. To + // be safe, set the debug location for it to the location of the + // return statement. Otherwise point it to end of the function's + // lexical scope. if (CGDebugInfo *DI = getDebugInfo()) { - if (NumSimpleReturnExprs == 1 && NumStopPoints == 1) - DI->EmitLocation(Builder, FirstStopPoint); + if (NumSimpleReturnExprs == NumReturnExprs) + DI->EmitLocation(Builder, LastStopPoint); else DI->EmitLocation(Builder, EndLoc); } @@ -206,14 +206,14 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // edges will be *really* confused. bool EmitRetDbgLoc = true; if (EHStack.stable_begin() != PrologueCleanupDepth) { - PopCleanupBlocks(PrologueCleanupDepth); + PopCleanupBlocks(PrologueCleanupDepth, EndLoc); // Make sure the line table doesn't jump back into the body for // the ret after it's been at EndLoc. EmitRetDbgLoc = false; if (CGDebugInfo *DI = getDebugInfo()) - if (NumSimpleReturnExprs == 1 && NumStopPoints == 1) + if (NumSimpleReturnExprs == NumReturnExprs) DI->EmitLocation(Builder, EndLoc); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 17df1dad3ef082b7c42324a337cfd0f2e828c85b..7c6e8d176b6071f121422c7c1532ffe704979a16 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -784,7 +784,9 @@ public: /// PopCleanupBlock - Will pop the cleanup entry on the stack and /// process all branch fixups. - void PopCleanupBlock(bool FallThroughIsBranchThrough = false); + /// \param EHLoc - Optional debug location for EH code. + void PopCleanupBlock(bool FallThroughIsBranchThrough = false, + SourceLocation EHLoc=SourceLocation()); /// DeactivateCleanupBlock - Deactivates the given cleanup block. /// The block cannot be reactivated. Pops it if it's the top of the @@ -905,7 +907,9 @@ public: /// PopCleanupBlocks - Takes the old cleanup stack size and emits /// the cleanup blocks that have been added. - void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize); + /// \param EHLoc - Optional debug location for EH code. + void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize, + SourceLocation EHLoc=SourceLocation()); void ResolveBranchFixups(llvm::BasicBlock *Target); @@ -1206,14 +1210,14 @@ private: /// lazily by getUnreachableBlock(). llvm::BasicBlock *UnreachableBlock; - /// Counts of the number of distinct breakpoint locations in this function. - unsigned NumStopPoints; + /// Counts of the number return expressions in the function. + unsigned NumReturnExprs; /// Count the number of simple (constant) return expressions in the function. unsigned NumSimpleReturnExprs; - /// The first debug location (breakpoint) in the function. - SourceLocation FirstStopPoint; + /// The last regular (non-return) debug location (breakpoint) in the function. + SourceLocation LastStopPoint; public: /// A scope within which we are constructing the fields of an object which diff --git a/clang/test/CodeGenCXX/linetable-cleanup.cpp b/clang/test/CodeGenCXX/linetable-cleanup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4077af6d8e012451070f2ba501357736ac1fdf90 --- /dev/null +++ b/clang/test/CodeGenCXX/linetable-cleanup.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s + +// Check the line numbers for cleanup code with EH in combinatin with +// simple return expressions. + +// CHECK: define {{.*}}foo +// CHECK: call void @_ZN1CD1Ev(%class.C* {{.*}}), !dbg ![[CLEANUP:[0-9]+]] +// CHECK: ret i32 0, !dbg ![[RET:[0-9]+]] + +class C { +public: + ~C() {} + int i; +}; + +int foo() +{ + C c; + c.i = 42; + // This breakpoint should be at/before the cleanup code. + // CHECK: ![[CLEANUP]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return 0; + // CHECK: ![[RET]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +}