From 7095c767d444b4444563213f6882b28014c2e60e Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl@apple.com>
Date: Fri, 17 Jan 2014 00:15:10 +0000
Subject: [PATCH] Debug info: Refactor NoLocation and ArtificialLocation to use
 a common base class and use it pervasively to restore debug locations. Fixes
 an interaction between cleanup and EH that caused the location to not be
 restored properly after emitting a landing pad. rdar://problem/15208190

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199444 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/CGCleanup.cpp        |  4 ++-
 lib/CodeGen/CGDebugInfo.cpp      | 29 +++++++++++----------
 lib/CodeGen/CGDebugInfo.h        | 29 +++++++++++++--------
 lib/CodeGen/CGException.cpp      |  8 ++----
 test/CodeGenCXX/linetable-eh.cpp | 43 ++++++++++++++++++++++++++++++++
 5 files changed, 82 insertions(+), 31 deletions(-)
 create mode 100644 test/CodeGenCXX/linetable-eh.cpp

diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index c4e7880196e..4983ce93437 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -860,7 +860,9 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
 
   // Emit the EH cleanup if required.
   if (RequiresEHCleanup) {
-    if (CGDebugInfo *DI = getDebugInfo())
+    CGDebugInfo *DI = getDebugInfo();
+    SaveAndRestoreLocation AutoRestoreLocation(*this, Builder);
+    if (DI)
       DI->EmitLocation(Builder, CurEHLocation);
 
     CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 2977ed22230..3edffa56566 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -53,29 +53,34 @@ CGDebugInfo::~CGDebugInfo() {
 }
 
 
-NoLocation::NoLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+SaveAndRestoreLocation::SaveAndRestoreLocation(CodeGenFunction &CGF, CGBuilderTy &B)
   : DI(CGF.getDebugInfo()), Builder(B) {
   if (DI) {
     SavedLoc = DI->getLocation();
     DI->CurLoc = SourceLocation();
-    Builder.SetCurrentDebugLocation(llvm::DebugLoc());
   }
 }
 
+SaveAndRestoreLocation::~SaveAndRestoreLocation() {
+  if (DI)
+    DI->EmitLocation(Builder, SavedLoc);
+}
+
+NoLocation::NoLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+  : SaveAndRestoreLocation(CGF, B) {
+  if (DI)
+    Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+}
+
 NoLocation::~NoLocation() {
-  if (DI) {
+  if (DI)
     assert(Builder.getCurrentDebugLocation().isUnknown());
-    DI->CurLoc = SavedLoc;
-  }
 }
 
 ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B)
-  : DI(CGF.getDebugInfo()), Builder(B) {
-  if (DI) {
-    SavedLoc = DI->getLocation();
-    DI->CurLoc = SourceLocation();
+  : SaveAndRestoreLocation(CGF, B) {
+  if (DI)
     Builder.SetCurrentDebugLocation(llvm::DebugLoc());
-  }
 }
 
 void ArtificialLocation::Emit() {
@@ -91,10 +96,8 @@ void ArtificialLocation::Emit() {
 }
 
 ArtificialLocation::~ArtificialLocation() {
-  if (DI) {
+  if (DI)
     assert(Builder.getCurrentDebugLocation().getLine() == 0);
-    DI->CurLoc = SavedLoc;
-  }
 }
 
 void CGDebugInfo::setLocation(SourceLocation Loc) {
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 0ca274f5688..fce56c0513c 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -47,8 +47,8 @@ namespace CodeGen {
 /// and is responsible for emitting to llvm globals or pass directly to
 /// the backend.
 class CGDebugInfo {
-  friend class NoLocation;
   friend class ArtificialLocation;
+  friend class SaveAndRestoreLocation;
   CodeGenModule &CGM;
   const CodeGenOptions::DebugInfoKind DebugKind;
   llvm::DIBuilder DBuilder;
@@ -394,16 +394,26 @@ private:
   }
 };
 
-/// NoLocation - An RAII object that temporarily disables debug
-/// locations. This is useful for emitting instructions that should be
-/// counted towards the function prologue.
-class NoLocation {
+/// SaveAndRestoreLocation - An RAII object saves the current location
+/// and automatically restores it to the original value.
+class SaveAndRestoreLocation {
+protected:
   SourceLocation SavedLoc;
   CGDebugInfo *DI;
   CGBuilderTy &Builder;
+public:
+  SaveAndRestoreLocation(CodeGenFunction &CGF, CGBuilderTy &B);
+  /// Autorestore everything back to normal.
+  ~SaveAndRestoreLocation();
+};
+
+/// NoLocation - An RAII object that temporarily disables debug
+/// locations. This is useful for emitting instructions that should be
+/// counted towards the function prologue.
+class NoLocation : public SaveAndRestoreLocation {
 public:
   NoLocation(CodeGenFunction &CGF, CGBuilderTy &B);
-  /// ~NoLocation - Autorestore everything back to normal.
+  /// Autorestore everything back to normal.
   ~NoLocation();
 };
 
@@ -418,10 +428,7 @@ public:
 /// This is necessary because passing an empty SourceLocation to
 /// CGDebugInfo::setLocation() will result in the last valid location
 /// being reused.
-class ArtificialLocation {
-  SourceLocation SavedLoc;
-  CGDebugInfo *DI;
-  CGBuilderTy &Builder;
+class ArtificialLocation : public SaveAndRestoreLocation {
 public:
   ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B);
 
@@ -429,7 +436,7 @@ public:
   /// (= the top of the LexicalBlockStack).
   void Emit();
 
-  /// ~ArtificialLocation - Autorestore everything back to normal.
+  /// Autorestore everything back to normal.
   ~ArtificialLocation();
 };
 
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 8a43794281d..cc03b0a8d5b 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -766,11 +766,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
 
   // Save the current IR generation state.
   CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
-  SourceLocation SavedLocation;
-  if (CGDebugInfo *DI = getDebugInfo()) {
-    SavedLocation = DI->getLocation();
+  SaveAndRestoreLocation AutoRestoreLocation(*this, Builder);
+  if (CGDebugInfo *DI = getDebugInfo())
     DI->EmitLocation(Builder, CurEHLocation);
-  }
 
   const EHPersonality &personality = EHPersonality::get(getLangOpts());
 
@@ -892,8 +890,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
 
   // Restore the old IR generation state.
   Builder.restoreIP(savedIP);
-  if (CGDebugInfo *DI = getDebugInfo())
-    DI->EmitLocation(Builder, SavedLocation);
 
   return lpad;
 }
diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp
new file mode 100644
index 00000000000..d190c64c01d
--- /dev/null
+++ b/test/CodeGenCXX/linetable-eh.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s
+
+// Test that emitting a landing pad does not affect the line table
+// entries for the code that triggered it.
+
+// CHECK: call void @llvm.dbg.declare
+// CHECK: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[CURRENT_ADDR:.*]]), !dbg ![[DBG1:.*]]
+// CHECK: unwind label %{{.*}}, !dbg ![[DBG1]]
+// CHECK: store i64 %{{.*}}, i64* %current_address, align 8, !dbg ![[DBG1]]
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[FOUND_IT:.*]]), !dbg ![[DBG2:.*]]
+// CHECK: = landingpad
+// CHECK-NEXT: cleanup, !dbg ![[DBG3:.*]]
+// CHECK-DAG: ![[CURRENT_ADDR]] = {{.*}} [current_address]
+// CHECK-DAG: ![[FOUND_IT]] = {{.*}} [found_it]
+// CHECK-DAG: ![[DBG1]] = metadata !{i32 256,
+// CHECK-DAG: ![[DBG2]] = metadata !{i32 257,
+// CHECK-DAG: ![[DBG3]] = metadata !{i32 268,
+typedef unsigned long long uint64_t;
+template<class _Tp> class shared_ptr {
+public:
+  typedef _Tp element_type;
+  element_type* __ptr_;
+  ~shared_ptr();
+  element_type* operator->() const noexcept {return __ptr_;}
+};
+class Context {
+public:
+    uint64_t GetIt();
+};
+class Foo
+{
+    bool bar();
+    virtual shared_ptr<Context> GetContext () = 0;
+};
+# 253 "Foo.cpp" 3
+bool
+Foo::bar ()
+{
+  uint64_t current_address = GetContext()->GetIt();
+  bool found_it = false;
+# 267 "Foo.cpp" 3
+  return found_it;
+}
-- 
GitLab