From: Ted Kremenek Date: Tue, 7 May 2013 21:12:06 +0000 (+0000) Subject: [analyzer;alternate arrows] Fix inconsistencies in recorded location context when... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=be0b207c4916f823497d31cbf5083efb4e374163;p=clang [analyzer;alternate arrows] Fix inconsistencies in recorded location context when handling interprocedural paths. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181362 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 2b3b174f60..ad41e5fe38 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1587,26 +1587,82 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, N = NextNode; NextNode = N->getFirstPred(); ProgramPoint P = N->getLocation(); - const LocationContext *LC = N->getLocationContext(); - assert(!LCM[&PD.getActivePath()] || LCM[&PD.getActivePath()] == LC); - LCM[&PD.getActivePath()] = LC; - PathDiagnosticLocation &PrevLoc = PrevLocMap[LC->getCurrentStackFrame()]; do { - if (Optional PS = P.getAs()) { - // For expressions, make sure we propagate the - // interesting symbols correctly. - if (const Expr *Ex = PS->getStmtAs()) - reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, - N->getState().getPtr(), Ex, - N->getLocationContext()); + // Have we encountered an entrance to a call? It may be + // the case that we have not encountered a matching + // call exit before this point. This means that the path + // terminated within the call itself. + if (Optional CE = P.getAs()) { + // Add an edge to the start of the function. + const StackFrameContext *CalleeLC = CE->getCalleeContext(); + PathDiagnosticLocation &PrevLocCallee = PrevLocMap[CalleeLC]; + const Decl *D = CalleeLC->getDecl(); + addEdgeToPath(PD.getActivePath(), PrevLocCallee, + PathDiagnosticLocation::createBegin(D, SM), + CalleeLC); - PathDiagnosticLocation L = - PathDiagnosticLocation(PS->getStmt(), SM, LC); - addEdgeToPath(PD.getActivePath(), PrevLoc, L, LC); + // Did we visit an entire call? + bool VisitedEntireCall = PD.isWithinCall(); + PD.popActivePath(); + + PathDiagnosticCallPiece *C; + if (VisitedEntireCall) { + PathDiagnosticPiece *P = PD.getActivePath().front().getPtr(); + C = cast(P); + } else { + const Decl *Caller = CE->getLocationContext()->getDecl(); + C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); + + // Since we just transferred the path over to the call piece, + // reset the mapping from active to location context. + assert(PD.getActivePath().size() == 1 && + PD.getActivePath().front() == C); + LCM[&PD.getActivePath()] = 0; + + // Record the location context mapping for the path within + // the call. + assert(LCM[&C->path] == 0 || + LCM[&C->path] == CE->getCalleeContext()); + LCM[&C->path] = CE->getCalleeContext(); + + // If this is the first item in the active path, record + // the new mapping from active path to location context. + const LocationContext *&NewLC = LCM[&PD.getActivePath()]; + if (!NewLC) { + NewLC = N->getLocationContext(); + } + PDB.LC = NewLC; + + // Update the previous location in the active path + // since we just created the call piece lazily. + PrevLocMap[PDB.LC->getCurrentStackFrame()] = C->getLocation(); + } + C->setCallee(*CE, SM); + + if (!CallStack.empty()) { + assert(CallStack.back().first == C); + CallStack.pop_back(); + } break; } + // Query the location context here and the previous location + // as processing CallEnter may change the active path. + PDB.LC = N->getLocationContext(); + + // Get the previous location for the current active + // location context. All edges will be based on this + // location, and it will be updated in place. + PathDiagnosticLocation &PrevLoc = + PrevLocMap[PDB.LC->getCurrentStackFrame()]; + + // Record the mapping from the active path to the location + // context. + assert(!LCM[&PD.getActivePath()] || + LCM[&PD.getActivePath()] == PDB.LC); + LCM[&PD.getActivePath()] = PDB.LC; + // Have we encountered an exit from a function call? if (Optional CE = P.getAs()) { const Stmt *S = CE->getCalleeContext()->getCallSite(); @@ -1626,7 +1682,8 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, LCM[&C->path] = CE->getCalleeContext(); // Add the edge to the return site. - addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, LC); + addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC); + PD.getActivePath().push_front(C); // Make the contents of the call the active path for now. PD.pushActivePath(&C->path); @@ -1634,34 +1691,17 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, break; } - // Have we encountered an entrance to a call? It may be - // the case that we have not encountered a matching - // call exit before this point. This means that the path - // terminated within the call itself. - if (Optional CE = P.getAs()) { - // Add an edge to the start of the function. - const Decl *D = CE->getCalleeContext()->getDecl(); - addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, SM), LC); - - // Did we visit an entire call? - bool VisitedEntireCall = PD.isWithinCall(); - PD.popActivePath(); - - PathDiagnosticCallPiece *C; - if (VisitedEntireCall) { - C = cast(PD.getActivePath().front()); - } else { - const Decl *Caller = CE->getLocationContext()->getDecl(); - C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); - LCM[&C->path] = CE->getCalleeContext(); - } - C->setCallee(*CE, SM); + if (Optional PS = P.getAs()) { + // For expressions, make sure we propagate the + // interesting symbols correctly. + if (const Expr *Ex = PS->getStmtAs()) + reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, + N->getState().getPtr(), Ex, + N->getLocationContext()); - if (!CallStack.empty()) { - assert(CallStack.back().first == C); - CallStack.pop_back(); - } + PathDiagnosticLocation L = + PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); + addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); break; } @@ -1688,7 +1728,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, "of the loop"); p->setPrunable(true); - addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC); + addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); PD.getActivePath().push_front(p); } @@ -1720,14 +1760,14 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, new PathDiagnosticEventPiece(L, str); PE->setPrunable(true); addEdgeToPath(PD.getActivePath(), PrevLoc, - PE->getLocation(), LC); + PE->getLocation(), PDB.LC); PD.getActivePath().push_front(PE); } } else if (isa(Term) || isa(Term) || isa(Term)) { PathDiagnosticLocation L(Term, SM, PDB.LC); - addEdgeToPath(PD.getActivePath(), PrevLoc, L, LC); + addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); } } break; @@ -1737,12 +1777,17 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, if (!NextNode) continue; + // Since the active path may have been updated prior + // to this point, query the active location context now. + PathDiagnosticLocation &PrevLoc = + PrevLocMap[PDB.LC->getCurrentStackFrame()]; + // Add pieces from custom visitors. for (ArrayRef::iterator I = visitors.begin(), E = visitors.end(); I != E; ++I) { if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *report)) { - addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC); + addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); PD.getActivePath().push_front(p); updateStackPiecesWithMessage(p, CallStack); }