diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 11a3befcb1d..df78b49130c 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -627,6 +627,21 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, ExplodedNodeSet &Dst) { + // This method acts upon CFG elements for logical operators && and || + // and attaches the value (true or false) to them as expressions. + // It doesn't produce any state splits. + // If we made it that far, we're past the point when we modeled the short + // circuit. It means that we should have precise knowledge about whether + // we've short-circuited. If we did, we already know the value we need to + // bind. If we didn't, the value of the RHS (casted to the boolean type) + // is the answer. + // Currently this method tries to figure out whether we've short-circuited + // by looking at the ExplodedGraph. This method is imperfect because there + // could inevitably have been merges that would have resulted in multiple + // potential path traversal histories. We bail out when we fail. + // Due to this ambiguity, a more reliable solution would have been to + // track the short circuit operation history path-sensitively until + // we evaluate the respective logical operator. assert(B->getOpcode() == BO_LAnd || B->getOpcode() == BO_LOr); @@ -648,10 +663,20 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, ProgramPoint P = N->getLocation(); assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); (void) P; - assert(N->pred_size() == 1); + if (N->pred_size() != 1) { + // We failed to track back where we came from. + Bldr.generateNode(B, Pred, state); + return; + } N = *N->pred_begin(); } - assert(N->pred_size() == 1); + + if (N->pred_size() != 1) { + // We failed to track back where we came from. + Bldr.generateNode(B, Pred, state); + return; + } + N = *N->pred_begin(); BlockEdge BE = N->getLocation().castAs<BlockEdge>(); SVal X; |