[analyzer] add a diagnostic event when entering a call via inlining, within the callee, and add an edge.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152086 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 965ac30..245d5be 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -387,6 +387,7 @@
const Decl *Callee;
public:
PathDiagnosticLocation callEnter;
+ PathDiagnosticLocation callEnterWithin;
PathDiagnosticLocation callReturn;
PathPieces path;
@@ -402,6 +403,8 @@
}
IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const;
+ IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+ getCallEnterWithinCallerEvent() const;
IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const;
virtual void flattenLocations() {
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 73e00e4..53fedaf 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1233,10 +1233,18 @@
// Pop the call hierarchy if we are done walking the contents
// of a function call.
if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) {
+ // Add an edge to the start of the function.
+ const Decl *D = CE->getCalleeContext()->getDecl();
+ PathDiagnosticLocation pos =
+ PathDiagnosticLocation::createBegin(D, SM);
+ EB.addEdge(pos);
+
+ // Flush all locations, and pop the active path.
EB.flushLocations();
PD.popActivePath();
assert(!PD.getActivePath().empty());
PDB.LC = N->getLocationContext();
+
// The current active path should never be empty. Either we
// just added a bunch of stuff to the top-level path, or
// we have a previous CallExit. If the front of the active
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index a082bba..01b40b4 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -527,7 +527,8 @@
const Decl *D = CE.getCalleeContext()->getDecl();
Callee = D;
callEnter = PathDiagnosticLocation(CE.getCallExpr(), SM,
- CE.getLocationContext());
+ CE.getLocationContext());
+ callEnterWithin = PathDiagnosticLocation::createBegin(D, SM);
}
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
@@ -537,16 +538,32 @@
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
if (isa<BlockDecl>(Callee))
- Out << "Entering call to block";
+ Out << "Calling anonymous block";
else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Callee))
- Out << "Entering call to '" << *ND << "'";
+ Out << "Calling '" << *ND << "'";
StringRef msg = Out.str();
if (msg.empty())
return 0;
return new PathDiagnosticEventPiece(callEnter, msg);
}
-IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
+ if (!Callee)
+ return 0;
+ SmallString<256> buf;
+ llvm::raw_svector_ostream Out(buf);
+ if (isa<BlockDecl>(Callee))
+ Out << "Entered call to block";
+ else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Callee))
+ Out << "Entered call to '" << *ND << "'";
+ StringRef msg = Out.str();
+ if (msg.empty())
+ return 0;
+ return new PathDiagnosticEventPiece(callEnterWithin, msg);
+}
+
+IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallExitEvent() const {
if (!Caller)
return 0;
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 6f2a5ca..2c8270a 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -255,15 +255,23 @@
IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnter =
P.getCallEnterEvent();
+
if (callEnter)
ReportPiece(o, *callEnter, FM, SM, LangOpts, indent, true);
+ IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnterWithinCaller =
+ P.getCallEnterWithinCallerEvent();
+
+ if (callEnterWithinCaller)
+ ReportPiece(o, *callEnterWithinCaller, FM, SM, LangOpts, indent, true);
+
for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
ReportPiece(o, **I, FM, SM, LangOpts, indent, true);
IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit =
P.getCallExitEvent();
- if (callExit)
+
+ if (callExit)
ReportPiece(o, *callExit, FM, SM, LangOpts, indent, true);
}
diff --git a/test/Analysis/inline-unique-reports.c b/test/Analysis/inline-unique-reports.c
index f5e5b36..c99a303 100644
--- a/test/Analysis/inline-unique-reports.c
+++ b/test/Analysis/inline-unique-reports.c
@@ -84,9 +84,56 @@
// CHECK: </array>
// CHECK: </array>
// CHECK: <key>extended_message</key>
-// CHECK: <string>Entering call to 'bug'</string>
+// CHECK: <string>Calling 'bug'</string>
// CHECK: <key>message</key>
-// CHECK: <string>Entering call to 'bug'</string>
+// CHECK: <string>Calling 'bug'</string>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>event</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>1</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <key>extended_message</key>
+// CHECK: <string>Entered call to 'bug'</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Entered call to 'bug'</string>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>1</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>4</integer>
+// CHECK: <key>col</key><integer>1</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>5</integer>
+// CHECK: <key>col</key><integer>4</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
// CHECK: </dict>
// CHECK: <dict>
// CHECK: <key>kind</key><string>event</string>