[analyzer] InnerPointerChecker: improve warning messages and notes.

Differential Revision: https://reviews.llvm.org/D49570

llvm-svn: 339489
diff --git a/clang/lib/StaticAnalyzer/Checkers/AllocationState.h b/clang/lib/StaticAnalyzer/Checkers/AllocationState.h
index a6908bd..c8193f7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/AllocationState.h
+++ b/clang/lib/StaticAnalyzer/Checkers/AllocationState.h
@@ -26,6 +26,11 @@
 /// AF_InnerBuffer symbols.
 std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym);
 
+/// 'Sym' represents a pointer to the inner buffer of a container object.
+/// This function looks up the memory region of that object in
+/// DanglingInternalBufferChecker's program state map.
+const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym);
+
 } // end namespace allocation_state
 
 } // end namespace ento
diff --git a/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
index b2e49f2..926a1d7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
@@ -279,6 +279,28 @@
   C.addTransition(State);
 }
 
+namespace clang {
+namespace ento {
+namespace allocation_state {
+
+std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym) {
+  return llvm::make_unique<InnerPointerChecker::InnerPointerBRVisitor>(Sym);
+}
+
+const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym) {
+  RawPtrMapTy Map = State->get<RawPtrMap>();
+  for (const auto Entry : Map) {
+    if (Entry.second.contains(Sym)) {
+      return Entry.first;
+    }
+  }
+  return nullptr;
+}
+
+} // end namespace allocation_state
+} // end namespace ento
+} // end namespace clang
+
 std::shared_ptr<PathDiagnosticPiece>
 InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N,
                                                       const ExplodedNode *PrevN,
@@ -292,27 +314,21 @@
   if (!S)
     return nullptr;
 
+  const MemRegion *ObjRegion =
+      allocation_state::getContainerObjRegion(N->getState(), PtrToBuf);
+  const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
+  QualType ObjTy = TypedRegion->getValueType();
+
   SmallString<256> Buf;
   llvm::raw_svector_ostream OS(Buf);
-  OS << "Dangling inner pointer obtained here";
+  OS << "Pointer to inner buffer of '" << ObjTy.getAsString()
+     << "' obtained here";
   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
                              N->getLocationContext());
   return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
                                                     nullptr);
 }
 
-namespace clang {
-namespace ento {
-namespace allocation_state {
-
-std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym) {
-  return llvm::make_unique<InnerPointerChecker::InnerPointerBRVisitor>(Sym);
-}
-
-} // end namespace allocation_state
-} // end namespace ento
-} // end namespace clang
-
 void ento::registerInnerPointerChecker(CheckerManager &Mgr) {
   registerInnerPointerCheckerAux(Mgr);
   Mgr.registerChecker<InnerPointerChecker>();
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 89413c2..5e78cf6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1996,15 +1996,20 @@
       BT_UseFree[*CheckKind].reset(new BugType(
           CheckNames[*CheckKind], "Use-after-free", categories::MemoryError));
 
+    AllocationFamily AF =
+        C.getState()->get<RegionState>(Sym)->getAllocationFamily();
+
     auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
-                                         "Use of memory after it is freed", N);
+        AF == AF_InnerBuffer
+              ? "Inner pointer of container used after re/deallocation"
+              : "Use of memory after it is freed",
+        N);
 
     R->markInteresting(Sym);
     R->addRange(Range);
     R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
 
-    const RefState *RS = C.getState()->get<RegionState>(Sym);
-    if (RS->getAllocationFamily() == AF_InnerBuffer)
+    if (AF == AF_InnerBuffer)
       R->addVisitor(allocation_state::getInnerPointerBRVisitor(Sym));
 
     C.emitReport(std::move(R));
@@ -2944,13 +2949,22 @@
         case AF_CXXNewArray:
         case AF_IfNameIndex:
           Msg = "Memory is released";
+          StackHint = new StackHintGeneratorForSymbol(Sym,
+                                              "Returning; memory was released");
           break;
         case AF_InnerBuffer: {
-          OS << "Inner pointer invalidated by call to ";
+          const MemRegion *ObjRegion =
+              allocation_state::getContainerObjRegion(statePrev, Sym);
+          const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
+          QualType ObjTy = TypedRegion->getValueType();
+          OS << "Inner buffer of '" << ObjTy.getAsString() << "' ";
+
           if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) {
-            OS << "destructor";
+            OS << "deallocated by call to destructor";
+            StackHint = new StackHintGeneratorForSymbol(Sym,
+                                      "Returning; inner buffer was deallocated");
           } else {
-            OS << "'";
+            OS << "reallocated by call to '";
             const Stmt *S = RS->getStmt();
             if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
               OS << MemCallE->getMethodDecl()->getNameAsString();
@@ -2963,6 +2977,8 @@
               OS << (D ? D->getNameAsString() : "unknown");
             }
             OS << "'";
+            StackHint = new StackHintGeneratorForSymbol(Sym,
+                                      "Returning; inner buffer was reallocated");
           }
           Msg = OS.str();
           break;
@@ -2970,8 +2986,6 @@
         case AF_None:
           llvm_unreachable("Unhandled allocation family!");
       }
-      StackHint = new StackHintGeneratorForSymbol(Sym,
-                                             "Returning; memory was released");
 
       // See if we're releasing memory while inlining a destructor
       // (or one of its callees). This turns on various common