forked from OSchip/llvm-project
[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:
parent
e781266905
commit
04e860df2c
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,9 +84,56 @@ void test_bug_2() {
|
|||
// 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>
|
||||
|
|
Loading…
Reference in New Issue