From: Ted Kremenek Date: Tue, 6 Mar 2012 01:25:01 +0000 (+0000) Subject: [analyzer] add a diagnostic event when entering a call via inlining, within the calle... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898;p=clang [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 965ac3085e..245d5be93e 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/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 getCallEnterEvent() const; + IntrusiveRefCntPtr + getCallEnterWithinCallerEvent() const; IntrusiveRefCntPtr getCallExitEvent() const; virtual void flattenLocations() { diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 73e00e4416..53fedaf2a1 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/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(&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 a082bba70d..01b40b43ba 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/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 @@ -537,16 +538,32 @@ PathDiagnosticCallPiece::getCallEnterEvent() const { SmallString<256> buf; llvm::raw_svector_ostream Out(buf); if (isa(Callee)) - Out << "Entering call to block"; + Out << "Calling anonymous block"; else if (const NamedDecl *ND = dyn_cast(Callee)) - Out << "Entering call to '" << *ND << "'"; + Out << "Calling '" << *ND << "'"; StringRef msg = Out.str(); if (msg.empty()) return 0; return new PathDiagnosticEventPiece(callEnter, msg); } -IntrusiveRefCntPtr +IntrusiveRefCntPtr +PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const { + if (!Callee) + return 0; + SmallString<256> buf; + llvm::raw_svector_ostream Out(buf); + if (isa(Callee)) + Out << "Entered call to block"; + else if (const NamedDecl *ND = dyn_cast(Callee)) + Out << "Entered call to '" << *ND << "'"; + StringRef msg = Out.str(); + if (msg.empty()) + return 0; + return new PathDiagnosticEventPiece(callEnterWithin, msg); +} + +IntrusiveRefCntPtr PathDiagnosticCallPiece::getCallExitEvent() const { if (!Caller) return 0; diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp index 6f2a5ca931..2c8270a2dd 100644 --- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -255,15 +255,23 @@ static void ReportCall(raw_ostream &o, IntrusiveRefCntPtr callEnter = P.getCallEnterEvent(); + if (callEnter) ReportPiece(o, *callEnter, FM, SM, LangOpts, indent, true); + IntrusiveRefCntPtr 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 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 f5e5b36be7..c99a303335 100644 --- a/test/Analysis/inline-unique-reports.c +++ b/test/Analysis/inline-unique-reports.c @@ -84,9 +84,56 @@ void test_bug_2() { // CHECK: // CHECK: // CHECK: extended_message -// CHECK: Entering call to 'bug' +// CHECK: Calling 'bug' // CHECK: message -// CHECK: Entering call to 'bug' +// CHECK: Calling 'bug' +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line4 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: extended_message +// CHECK: Entered call to 'bug' +// CHECK: message +// CHECK: Entered call to 'bug' +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line4 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line4 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line5 +// CHECK: col3 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line5 +// CHECK: col4 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: // CHECK: // CHECK: // CHECK: kindevent