summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h3
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp8
-rw-r--r--clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp25
-rw-r--r--clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp10
-rw-r--r--clang/test/Analysis/inline-unique-reports.c51
5 files changed, 90 insertions, 7 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 965ac3085e6..245d5be93e6 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -387,6 +387,7 @@ class PathDiagnosticCallPiece : public PathDiagnosticPiece {
const Decl *Callee;
public:
PathDiagnosticLocation callEnter;
+ PathDiagnosticLocation callEnterWithin;
PathDiagnosticLocation callReturn;
PathPieces path;
@@ -402,6 +403,8 @@ public:
}
IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const;
+ IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+ getCallEnterWithinCallerEvent() const;
IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const;
virtual void flattenLocations() {
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 73e00e44167..53fedaf2a12 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1233,10 +1233,18 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
// 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/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index a082bba70dd..01b40b43baf 100644
--- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -527,7 +527,8 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
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 @@ PathDiagnosticCallPiece::getCallEnterEvent() const {
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/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 6f2a5ca9313..2c8270a2dd1 100644
--- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -255,15 +255,23 @@ static void ReportCall(raw_ostream &o,
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/clang/test/Analysis/inline-unique-reports.c b/clang/test/Analysis/inline-unique-reports.c
index f5e5b36be71..c99a3033353 100644
--- a/clang/test/Analysis/inline-unique-reports.c
+++ b/clang/test/Analysis/inline-unique-reports.c
@@ -84,9 +84,56 @@ void test_bug_2() {
// CHECK: </array>
// CHECK: </array>
// CHECK: <key>extended_message</key>
-// CHECK: <string>Entering call to &apos;bug&apos;</string>
+// CHECK: <string>Calling &apos;bug&apos;</string>
// CHECK: <key>message</key>
-// CHECK: <string>Entering call to &apos;bug&apos;</string>
+// CHECK: <string>Calling &apos;bug&apos;</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 &apos;bug&apos;</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Entered call to &apos;bug&apos;</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>
OpenPOWER on IntegriCloud