Merge ArtificialLocation into ApplyDebugLocation and make a clear
distinction between the different use-cases. With the previous default
behavior we would occasionally emit empty debug locations in situations
where they actually were strictly required (= on invoke insns).
We now have a choice between defaulting to an empty location or an
artificial location.

Specifically, this fixes a bug caused by a missing debug location when
emitting C++ EH cleanup blocks from within an artificial function, such as
an ObjC destroy helper function.

rdar://problem/19670595

llvm-svn: 228003
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index b98460a..ffc6e57 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1178,7 +1178,7 @@
     Alloca->setAlignment(Align);
     // Set the DebugLocation to empty, so the store is recognized as a
     // frame setup instruction by llvm::DwarfDebug::beginFunction().
-    ApplyDebugLocation NL(*this);
+    ApplyDebugLocation NL(*this, ApplyDebugLocation::MarkAsPrologue);
     Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
     BlockPointerDbgLoc = Alloca;
   }
@@ -1328,10 +1328,10 @@
                                           nullptr, SC_Static,
                                           false,
                                           false);
-  // Create a scope with an artificial location for the body of this function.
-  ApplyDebugLocation NL(*this);
+  ApplyDebugLocation NL(*this, ApplyDebugLocation::MarkAsPrologue);
   StartFunction(FD, C.VoidTy, Fn, FI, args);
-  ArtificialLocation AL(*this);
+  // Create a scope with an artificial location for the body of this function.
+  ApplyDebugLocation AL(*this, ApplyDebugLocation::Artificial);
 
   llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
 
@@ -1500,9 +1500,9 @@
                                           nullptr, SC_Static,
                                           false, false);
   // Create a scope with an artificial location for the body of this function.
-  ApplyDebugLocation NL(*this);
+  ApplyDebugLocation NL(*this, ApplyDebugLocation::MarkAsPrologue);
   StartFunction(FD, C.VoidTy, Fn, FI, args);
-  ArtificialLocation AL(*this);
+  ApplyDebugLocation AL(*this, ApplyDebugLocation::Artificial);
 
   llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
 
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 18ed3e5..a75a7af 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -861,7 +861,7 @@
 
   // Emit the EH cleanup if required.
   if (RequiresEHCleanup) {
-    ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation);
+    ApplyDebugLocation AL(*this, ApplyDebugLocation::Artificial, CurEHLocation);
 
     CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
 
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 38a1184..3fb8393 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -52,28 +52,34 @@
          "Region stack mismatch, stack not empty!");
 }
 
-ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF)
-    : ApplyDebugLocation(CGF) {
-  if (auto *DI = CGF.getDebugInfo()) {
-    // Construct a location that has a valid scope, but no line info.
-    assert(!DI->LexicalBlockStack.empty());
-    llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
-    CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
-  }
-}
-
 ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
                                        SourceLocation TemporaryLocation)
     : CGF(CGF) {
+  assert(!TemporaryLocation.isInvalid() && "invalid location");
   init(TemporaryLocation);
 }
 
-void ApplyDebugLocation::init(SourceLocation TemporaryLocation) {
+ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
+                                       bool MarkAsPrologue,
+                                       SourceLocation TemporaryLocation)
+    : CGF(CGF) {
+  init(TemporaryLocation, MarkAsPrologue);
+}
+
+void ApplyDebugLocation::init(SourceLocation TemporaryLocation,
+                              bool MarkAsPrologue) {
   if (auto *DI = CGF.getDebugInfo()) {
     OriginalLocation = CGF.Builder.getCurrentDebugLocation();
-    if (TemporaryLocation.isInvalid())
-      CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc());
-    else
+    if (TemporaryLocation.isInvalid()) {
+      if (MarkAsPrologue)
+        CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+      else {
+        // Construct a location that has a valid scope, but no line info.
+        assert(!DI->LexicalBlockStack.empty());
+        llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
+        CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
+      }
+    } else
       DI->EmitLocation(CGF.Builder, TemporaryLocation);
   }
 }
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index e3d6724..2f0c3f5 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -47,7 +47,7 @@
 /// and is responsible for emitting to llvm globals or pass directly to
 /// the backend.
 class CGDebugInfo {
-  friend class ArtificialLocation;
+  friend class ApplyDebugLocation;
   friend class SaveAndRestoreLocation;
   CodeGenModule &CGM;
   const CodeGenOptions::DebugInfoKind DebugKind;
@@ -447,38 +447,36 @@
 /// location or preferred location of the specified Expr.
 class ApplyDebugLocation {
 private:
-  void init(SourceLocation TemporaryLocation);
+  void init(SourceLocation TemporaryLocation, bool MarkAsPrologue = false);
 
 protected:
   llvm::DebugLoc OriginalLocation;
   CodeGenFunction &CGF;
 
 public:
-  /// If TemporaryLocation is invalid, the IRBuilder will be set to not attach
-  /// debug locations, thus marking the instructions as prologue.
-  ApplyDebugLocation(CodeGenFunction &CGF,
+  enum { Artificial = false, MarkAsPrologue = true, NoLocation = true };
+
+  /// \brief Set the location to the (valid) TemporaryLocation.
+  ApplyDebugLocation(CodeGenFunction &CGF, SourceLocation TemporaryLocation);
+  /// \brief Apply TemporaryLocation if it is valid, or apply a default
+  /// location: If MarkAsPrologue is true, the IRBuilder will be set to not
+  /// attach debug locations, thus marking the instructions as
+  /// prologue. Otherwise this switches to an artificial debug location that has
+  /// a valid scope, but no line information.
+  ///
+  /// Artificial locations are useful when emitting compiler-generated helper
+  /// functions that have no source location associated with them. The DWARF
+  /// specification allows the compiler to use the special line number 0 to
+  /// indicate code that can not be attributed to any source location. Note that
+  /// passing an empty SourceLocation to CGDebugInfo::setLocation() will result
+  /// in the last valid location being reused.
+  ApplyDebugLocation(CodeGenFunction &CGF, bool MarkAsPrologue,
                      SourceLocation TemporaryLocation = SourceLocation());
   ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E);
   ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc);
   ~ApplyDebugLocation();
 };
 
-/// \brief An RAII object that temporarily switches to
-/// an artificial debug location that has a valid scope, but no line
-/// information. This is useful when emitting compiler-generated
-/// helper functions that have no source location associated with
-/// them. The DWARF specification allows the compiler to use the
-/// special line number 0 to indicate code that can not be attributed
-/// to any source location.
-///
-/// This is necessary because passing an empty SourceLocation to
-/// CGDebugInfo::setLocation() will result in the last valid location
-/// being reused.
-class ArtificialLocation : public ApplyDebugLocation {
-public:
-  ArtificialLocation(CodeGenFunction &CGF);
-};
-
 
 } // namespace CodeGen
 } // namespace clang
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 766d2aa..bada6ea 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1090,7 +1090,7 @@
   if (emission.wasEmittedAsGlobal()) return;
 
   const VarDecl &D = *emission.Variable;
-  ApplyDebugLocation DL(*this, D.getLocation());
+  ApplyDebugLocation DL(*this, ApplyDebugLocation::Artificial, D.getLocation());
   QualType type = D.getType();
 
   // If this local has an initializer, emit it now.
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 3b379b7..6303db6 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -469,11 +469,11 @@
                                            ArrayRef<llvm::Function *> Decls,
                                            llvm::GlobalVariable *Guard) {
   {
-    ApplyDebugLocation NL(*this);
+    ApplyDebugLocation NL(*this, ApplyDebugLocation::MarkAsPrologue);
     StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                   getTypes().arrangeNullaryFunction(), FunctionArgList());
     // Emit an artificial location for this function.
-    ArtificialLocation AL(*this);
+    ApplyDebugLocation AL(*this, ApplyDebugLocation::Artificial);
 
     llvm::BasicBlock *ExitBlock = nullptr;
     if (Guard) {
@@ -520,11 +520,11 @@
                   const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
                                                 &DtorsAndObjects) {
   {
-    ApplyDebugLocation NL(*this);
+    ApplyDebugLocation NL(*this, ApplyDebugLocation::MarkAsPrologue);
     StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                   getTypes().arrangeNullaryFunction(), FunctionArgList());
     // Emit an artificial location for this function.
-    ArtificialLocation AL(*this);
+    ApplyDebugLocation AL(*this, ApplyDebugLocation::Artificial);
 
     // Emit the dtors, in reverse order from construction.
     for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 9f886eb..406afb2 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -770,7 +770,7 @@
 
   // Save the current IR generation state.
   CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
-  ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation);
+  ApplyDebugLocation AL(*this, ApplyDebugLocation::Artificial, CurEHLocation);
 
   const EHPersonality &personality = EHPersonality::get(CGM);
 
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 2e2821b..503f9b1 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3043,7 +3043,7 @@
   // Emit an unconditional branch from this block to ContBlock.
   {
     // There is no need to emit line number for unconditional branch.
-    ApplyDebugLocation DL(CGF);
+    ApplyDebugLocation NL(CGF, ApplyDebugLocation::NoLocation);
     CGF.EmitBlock(ContBlock);
   }
   // Insert an entry into the phi node for the edge with the value of RHSCond.
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index e3bdf86..be2ddf6 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -564,8 +564,8 @@
   // Emit the 'else' code if present.
   if (const Stmt *Else = S.getElse()) {
     {
-      // There is no need to emit line number for unconditional branch.
-      ApplyDebugLocation DL(*this);
+      // There is no need to emit line number for an unconditional branch.
+      ApplyDebugLocation NL(*this, ApplyDebugLocation::NoLocation);
       EmitBlock(ElseBlock);
     }
     {
@@ -573,8 +573,8 @@
       EmitStmt(Else);
     }
     {
-      // There is no need to emit line number for unconditional branch.
-      ApplyDebugLocation DL(*this);
+      // There is no need to emit line number for an unconditional branch.
+      ApplyDebugLocation NL(*this, ApplyDebugLocation::NoLocation);
       EmitBranch(ContBlock);
     }
   }
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 60958d0..395f6fa 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -86,13 +86,13 @@
   // Emit the 'else' code if present.
   {
     // There is no need to emit line number for unconditional branch.
-    ApplyDebugLocation DL(CGF);
+    ApplyDebugLocation NL(CGF, ApplyDebugLocation::NoLocation);
     CGF.EmitBlock(ElseBlock);
   }
   CodeGen(/*ThenBlock*/ false);
   {
     // There is no need to emit line number for unconditional branch.
-    ApplyDebugLocation DL(CGF);
+    ApplyDebugLocation NL(CGF, ApplyDebugLocation::NoLocation);
     CGF.EmitBranch(ContBlock);
   }
   // Emit the continuation block for code after the if.