Author: szepet Date: Mon Aug 21 09:10:19 2017 New Revision: 311344 URL: http://llvm.org/viewvc/llvm-project?rev=311344&view=rev Log: [StaticAnalyzer] Handle LoopExit CFGElement in the analyzer
This patch adds handling of the LoopExit CFGElements to the StaticAnalyzer. This is reached by introducing a new ProgramPoint. Tests will be added in a following commit. Differential Revision: https://reviews.llvm.org/D35670 Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=311344&r1=311343&r2=311344&view=diff ============================================================================== --- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original) +++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Mon Aug 21 09:10:19 2017 @@ -83,6 +83,7 @@ public: PostImplicitCallKind, MinImplicitCallKind = PreImplicitCallKind, MaxImplicitCallKind = PostImplicitCallKind, + LoopExitKind, EpsilonKind}; private: @@ -654,6 +655,29 @@ private: } }; +/// Represents a point when we exit a loop. +/// When this ProgramPoint is encountered we can be sure that the symbolic +/// execution of the corresponding LoopStmt is finished on the given path. +/// Note: It is possible to encounter a LoopExit element when we haven't even +/// encountered the loop itself. At the current state not all loop exits will +/// result in a LoopExit program point. +class LoopExit : public ProgramPoint { +public: + LoopExit(const Stmt *LoopStmt, const LocationContext *LC) + : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {} + + const Stmt *getLoopStmt() const { + return static_cast<const Stmt *>(getData1()); + } + +private: + friend class ProgramPoint; + LoopExit() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == LoopExitKind; + } +}; + /// This is a meta program point, which should be skipped by all the diagnostic /// reasoning etc. class EpsilonPoint : public ProgramPoint { Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=311344&r1=311343&r2=311344&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Mon Aug 21 09:10:19 2017 @@ -196,6 +196,8 @@ public: void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); + void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred); + void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred); void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); Modified: cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=311344&r1=311343&r2=311344&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Mon Aug 21 09:10:19 2017 @@ -274,7 +274,8 @@ void CoreEngine::dispatchWorkItem(Explod assert(Loc.getAs<PostStmt>() || Loc.getAs<PostInitializer>() || Loc.getAs<PostImplicitCall>() || - Loc.getAs<CallExitEnd>()); + Loc.getAs<CallExitEnd>() || + Loc.getAs<LoopExit>()); HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred); break; } @@ -566,7 +567,8 @@ void CoreEngine::enqueueStmtNode(Explode // Do not create extra nodes. Move to the next CFG element. if (N->getLocation().getAs<PostInitializer>() || - N->getLocation().getAs<PostImplicitCall>()) { + N->getLocation().getAs<PostImplicitCall>()|| + N->getLocation().getAs<LoopExit>()) { WList->enqueue(N, Block, Idx+1); return; } Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=311344&r1=311343&r2=311344&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Aug 21 09:10:19 2017 @@ -364,8 +364,10 @@ void ExprEngine::processCFGElement(const case CFGElement::TemporaryDtor: ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred); return; - case CFGElement::LifetimeEnds: case CFGElement::LoopExit: + ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred); + return; + case CFGElement::LifetimeEnds: return; } } @@ -510,6 +512,21 @@ void ExprEngine::ProcessStmt(const CFGSt Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx); } +void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) { + PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), + S->getLocStart(), + "Error evaluating end of the loop"); + ExplodedNodeSet Dst; + Dst.Add(Pred); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); + + LoopExit PP(S, Pred->getLocationContext()); + Bldr.generateNode(PP, Pred->getState(), Pred); + + // Enqueue the new nodes onto the work list. + Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx); +} + void ExprEngine::ProcessInitializer(const CFGInitializer Init, ExplodedNode *Pred) { const CXXCtorInitializer *BMI = Init.getInitializer(); @@ -2689,6 +2706,12 @@ struct DOTGraphTraits<ExplodedNode*> : Out << "Epsilon Point"; break; + case ProgramPoint::LoopExitKind: { + LoopExit LE = Loc.castAs<LoopExit>(); + Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); + break; + } + case ProgramPoint::PreImplicitCallKind: { ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>(); Out << "PreCall: "; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits