[analyzer] add a diagnostic event when entering a call via inlining, within the callee, and add an edge.

llvm-svn: 152086
This commit is contained in:
Ted Kremenek 2012-03-06 01:25:01 +00:00
parent e781266905
commit 04e860df2c
5 changed files with 90 additions and 7 deletions

View File

@ -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() {

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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>