Add basic BugReporter support for CallEnter/CallExit.  WIP.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149939 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 6622e6e..0bc1532 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -3454,6 +3454,13 @@
       return;
   }
 
+  // If the current LocationContext has a parent, don't check for leaks.
+  // We will do that later.
+  // FIXME: we should instead check for imblances of the retain/releases,
+  // and suggest annotations.
+  if (Ctx.getLocationContext()->getParent())
+    return;
+  
   B = state->get<RefBindings>();
   SmallVector<SymbolRef, 10> Leaked;
 
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 94368b5..5101827 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1646,6 +1646,11 @@
   // Register additional node visitors.
   R->addVisitor(new NilReceiverBRVisitor());
   R->addVisitor(new ConditionBRVisitor());
+  
+  // If inlining is turning out, emit diagnostics for CallEnter and
+  // CallExit at the top level.
+  bool showTopLevel = Eng.getAnalysisManager().shouldInlineCall();
+  R->addVisitor(new CallEnterExitBRVisitor(showTopLevel));
 
   // Generate the very last diagnostic piece - the piece is visible before 
   // the trace is expanded.
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 230e7c9..68ec6b0 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -726,3 +726,54 @@
   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC);
   return new PathDiagnosticEventPiece(Loc, Out.str());
 }
+
+static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N,
+                                             const SourceManager &SM) {
+  while (N) {
+    ProgramPoint PP = N->getLocation();
+    if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP))
+      return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext());
+    if (N->pred_empty())
+      break;
+    N = *N->pred_begin();
+  }
+  return PathDiagnosticLocation();
+}
+
+PathDiagnosticPiece *
+CallEnterExitBRVisitor::VisitNode(const ExplodedNode *N,
+                                  const ExplodedNode *PrevN,
+                                  BugReporterContext &BRC,
+                                  BugReport &BR) {
+  ProgramPoint PP = N->getLocation();
+  SmallString<256> buf;
+  llvm::raw_svector_ostream Out(buf);
+  PathDiagnosticLocation pos;
+
+  if (const CallEnter *CEnter = dyn_cast<CallEnter>(&PP)) {
+    const Decl *callee = CEnter->getCalleeContext()->getDecl();
+    pos = PathDiagnosticLocation(CEnter->getCallExpr(), BRC.getSourceManager(),
+                                 PP.getLocationContext());
+    if (isa<BlockDecl>(callee))
+      Out << "Entering call to block";
+    else if (const NamedDecl *ND = dyn_cast<NamedDecl>(callee))
+      Out << "Entering call to '" << ND->getNameAsString() << "'";
+  }
+  else if (const CallExit *CExit = dyn_cast<CallExit>(&PP)) {
+    const Decl *caller = CExit->getLocationContext()->getParent()->getDecl();
+    pos = getLastStmtLoc(PrevN, BRC.getSourceManager());
+    if (const NamedDecl *ND = dyn_cast<NamedDecl>(caller))
+      Out << "Returning to " << ND->getNameAsString();
+    else
+      Out << "Returning to caller"; 
+  }
+  
+  if (!pos.isValid())
+    return 0;
+    
+  StringRef msg = Out.str();
+  if (msg.empty())
+    return 0;
+
+  return new PathDiagnosticEventPiece(pos, msg);
+}