From: Ted Kremenek Date: Tue, 21 May 2013 00:34:40 +0000 (+0000) Subject: [analyzer; alternate edges] optimize edges for ObjC fast enumeration loops. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e86ee1a213d244bb66b7eef3e9ab2266908cf4af;p=clang [analyzer; alternate edges] optimize edges for ObjC fast enumeration loops. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182342 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index fddb7e7216..3365d79a38 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1566,6 +1566,16 @@ static void addEdgeToPath(PathPieces &path, PrevLoc = NewLoc; } +/// A customized wrapper for CFGBlock::getTerminatorCondition() +/// which returns the element for ObjCForCollectionStmts. +static const Stmt *getTerminatorCondition(const CFGBlock *B) { + const Stmt *S = B->getTerminatorCondition(); + if (const ObjCForCollectionStmt *FS = + dyn_cast_or_null(S)) + return FS->getElement(); + return S; +} + static bool GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, PathDiagnosticBuilder &PDB, @@ -1693,9 +1703,14 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, N->getState().getPtr(), Ex, N->getLocationContext()); - PathDiagnosticLocation L = - PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); - addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); + // Add an edge. If this is an ObjCForCollectionStmt do + // not add an edge here as it appears in the CFG both + // as a terminator and as a terminator condition. + if (!isa(PS->getStmt())) { + PathDiagnosticLocation L = + PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); + addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); + } break; } @@ -1722,6 +1737,10 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, CS = dyn_cast(FS->getBody()); else if (const WhileStmt *WS = dyn_cast(Loop)) CS = dyn_cast(WS->getBody()); + else if (const ObjCForCollectionStmt *OFS = + dyn_cast(Loop)) { + CS = dyn_cast(OFS->getBody()); + } PathDiagnosticEventPiece *p = new PathDiagnosticEventPiece(L, "Looping back to the head " @@ -1745,7 +1764,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, // Are we jumping past the loop body without ever executing the // loop (because the condition was false)? if (isLoop(Term)) { - const Stmt *TermCond = BSrc->getTerminatorCondition(); + const Stmt *TermCond = getTerminatorCondition(BSrc); bool IsInLoopBody = isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term); @@ -2048,6 +2067,25 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM, } } + // Optimize edges for ObjC fast-enumeration loops. + // + // (X -> collection) -> (collection -> element) + // + // becomes: + // + // (X -> element) + if (s1End == s2Start) { + const ObjCForCollectionStmt *FS = + dyn_cast_or_null(level3); + if (FS && FS->getCollection()->IgnoreParens() == s2Start && + s2End == FS->getElement()) { + PieceI->setEndLocation(PieceNextI->getEndLocation()); + path.erase(NextI); + hasChanges = true; + continue; + } + } + // No changes at this index? Move to the next one. ++I; } @@ -2102,6 +2140,13 @@ static void adjustBranchEdges(PathPieces &pieces, LocationContextMap &LCM, Branch = IS; break; } + if (const ObjCForCollectionStmt *OFS = + dyn_cast(Parent)) { + if (OFS->getElement() == S) + Branch = OFS; + break; + } + S = Parent; }