[analyzer] Make sure calls in synthesized functions have valid path locations.

We do this by using the "most recent" good location: if a synthesized
function 'A' calls another function 'B', the path notes for the call to 'B'
will be placed at the same location as the path note for calling 'A'.

Similarly, the call to 'A' will have a note saying "Entered call from...",
and now we just don't emit that (since the user doesn't have a body to look
at anyway).

Previously, we were doing this for the "Calling..." notes, but not for the
"Entered call from..." or "Returning to caller". This caused a crash when
the path entered and then exiting a call within a synthesized body.

<rdar://problem/12657843>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168019 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index c898d65..c6689f8 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -193,7 +193,7 @@
 /// that aren't needed.  Return true if afterwards the path contains
 /// "interesting stuff" which means it should be pruned from the parent path.
 bool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R,
-                                     PathDiagnosticCallPiece *CallWithLoc) {
+                                     PathDiagnosticLocation *LastCallLocation) {
   bool containsSomethingInteresting = false;
   const unsigned N = pieces.size();
   
@@ -217,18 +217,24 @@
           containsSomethingInteresting = true;
           break;
         }
+
+        if (LastCallLocation) {
+          if (!call->callEnter.asLocation().isValid())
+            call->callEnter = *LastCallLocation;
+          if (!call->callReturn.asLocation().isValid())
+            call->callReturn = *LastCallLocation;
+        }
+
         // Recursively clean out the subclass.  Keep this call around if
         // it contains any informative diagnostics.
-        PathDiagnosticCallPiece *NewCallWithLoc =
-          call->getLocation().asLocation().isValid()
-            ? call : CallWithLoc;
-        
-        if (!RemoveUneededCalls(call->path, R, NewCallWithLoc))
-          continue;
+        if (call->callEnterWithin.asLocation().isValid())
+          LastCallLocation = &call->callEnterWithin;
+        else
+          LastCallLocation = &call->callEnter;
 
-        if (NewCallWithLoc == CallWithLoc && CallWithLoc) {
-          call->callEnter = CallWithLoc->callEnter;
-        }
+        assert(LastCallLocation && "Outermost call has an invalid location");
+        if (!RemoveUneededCalls(call->path, R, LastCallLocation))
+          continue;
         
         containsSomethingInteresting = true;
         break;