diff options
-rw-r--r-- | Analysis/GRExprEngine.cpp | 35 | ||||
-rw-r--r-- | Analysis/RValues.cpp | 30 | ||||
-rw-r--r-- | Analysis/ValueState.cpp | 26 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 12 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/RValues.h | 2 |
5 files changed, 66 insertions, 39 deletions
diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index 3bf0151180..b31f5e539f 100644 --- a/Analysis/GRExprEngine.cpp +++ b/Analysis/GRExprEngine.cpp @@ -92,6 +92,16 @@ ValueState* GRExprEngine::SetRVal(ValueState* St, LVal LV, RVal RV) { return StateMgr.SetRVal(St, LV, RV); } +ValueState* GRExprEngine::SetBlkExprRVal(ValueState* St, Expr* Ex, RVal V) { + + if (!StateCleaned) { + St = RemoveDeadBindings(CurrentStmt, St); + StateCleaned = true; + } + + return StateMgr.SetRVal(St, Ex, V, true, false); +} + ValueState* GRExprEngine::MarkBranch(ValueState* St, Stmt* Terminator, bool branchTaken) { @@ -420,7 +430,10 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { // dead mappings removed. if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) { - ValueState* St = RemoveDeadBindings(S, StmtEntryNode->getState()); + ValueState* St = + StateCleaned ? StmtEntryNode->getState() : + RemoveDeadBindings(S, StmtEntryNode->getState()); + builder.generateNode(S, St, StmtEntryNode); } @@ -442,7 +455,9 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){ // it to the block-level expression. ValueState* St = Pred->getState(); - Nodify(Dst, D, Pred, SetRVal(St, D, GetRVal(St, D))); + RVal X = RVal::MakeVal(BasicVals, D); + RVal Y = isa<lval::DeclVal>(X) ? GetRVal(St, cast<lval::DeclVal>(X)) : X; + Nodify(Dst, D, Pred, SetBlkExprRVal(St, D, Y)); } void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, @@ -1709,9 +1724,11 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : Out << S->getStmtClassName() << ' ' << (void*) S << ' '; S->printPretty(Out); - Out << "\\lline=" - << GraphPrintSourceManager->getLineNumber(SLoc) << " col=" - << GraphPrintSourceManager->getColumnNumber(SLoc) << "\\l"; + if (SLoc.isFileID()) { + Out << "\\lline=" + << GraphPrintSourceManager->getLineNumber(SLoc) << " col=" + << GraphPrintSourceManager->getColumnNumber(SLoc) << "\\l"; + } if (GraphPrintCheckerState->isImplicitNullDeref(N)) Out << "\\|Implicit-Null Dereference.\\l"; @@ -1750,9 +1767,11 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : E.getSrc()->printTerminator(Out); - Out << "\\lline=" - << GraphPrintSourceManager->getLineNumber(SLoc) << " col=" - << GraphPrintSourceManager->getColumnNumber(SLoc); + if (SLoc.isFileID()) { + Out << "\\lline=" + << GraphPrintSourceManager->getLineNumber(SLoc) << " col=" + << GraphPrintSourceManager->getColumnNumber(SLoc); + } if (isa<SwitchStmt>(T)) { Stmt* Label = E.getDst()->getLabel(); diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp index 9d5bd683a6..a4b464949a 100644 --- a/Analysis/RValues.cpp +++ b/Analysis/RValues.cpp @@ -238,6 +238,36 @@ RVal RVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) { LVal LVal::MakeVal(AddrLabelExpr* E) { return lval::GotoLabel(E->getLabel()); } //===----------------------------------------------------------------------===// +// Utility methods for constructing RVals (both NonLVals and LVals). +//===----------------------------------------------------------------------===// + +RVal RVal::MakeVal(BasicValueFactory& BasicVals, DeclRefExpr* E) { + + ValueDecl* D = cast<DeclRefExpr>(E)->getDecl(); + + if (VarDecl* VD = dyn_cast<VarDecl>(D)) { + return lval::DeclVal(VD); + } + else if (EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) { + + // FIXME: Do we need to cache a copy of this enum, since it + // already has persistent storage? We do this because we + // are comparing states using pointer equality. Perhaps there is + // a better way, since APInts are fairly lightweight. + + return nonlval::ConcreteInt(BasicVals.getValue(ED->getInitVal())); + } + else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) { + return lval::FuncVal(FD); + } + + assert (false && + "ValueDecl support for this ValueDecl not implemented."); + + return UnknownVal(); +} + +//===----------------------------------------------------------------------===// // Pretty-Printing. //===----------------------------------------------------------------------===// diff --git a/Analysis/ValueState.cpp b/Analysis/ValueState.cpp index 4eb2a5eb54..4b097ee4a4 100644 --- a/Analysis/ValueState.cpp +++ b/Analysis/ValueState.cpp @@ -232,28 +232,14 @@ RVal ValueStateManager::GetRVal(ValueState* St, Expr* E) { // within the referenced variables. case Stmt::DeclRefExprClass: { - - ValueDecl* D = cast<DeclRefExpr>(E)->getDecl(); - - if (VarDecl* VD = dyn_cast<VarDecl>(D)) { - return GetRVal(St, lval::DeclVal(VD)); - } - else if (EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) { - - // FIXME: Do we need to cache a copy of this enum, since it - // already has persistent storage? We do this because we - // are comparing states using pointer equality. Perhaps there is - // a better way, since APInts are fairly lightweight. - return nonlval::ConcreteInt(BasicVals.getValue(ED->getInitVal())); - } - else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) - return lval::FuncVal(FD); - - assert (false && - "ValueDecl support for this ValueDecl not implemented."); + // Check if this expression is a block-level expression. If so, + // return its value. + ValueState::ExprBindingsTy::TreeTy* T=St->BlockExprBindings.SlimFind(E); + if (T) return T->getValue().second; - return UnknownVal(); + RVal X = RVal::MakeVal(BasicVals, cast<DeclRefExpr>(E)); + return isa<lval::DeclVal>(X) ? GetRVal(St, cast<lval::DeclVal>(X)) : X; } case Stmt::CharacterLiteralClass: { diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 520c3732c8..37220ff5cd 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -275,17 +275,7 @@ protected: return SetRVal(St, const_cast<Expr*>(Ex), V); } - ValueState* SetBlkExprRVal(ValueState* St, Expr* Ex, RVal V) { - return StateMgr.SetRVal(St, Ex, V, true, false); - } - -#if 0 - /// SetRVal - This version of SetRVal is used to batch process a set - /// of different possible RVals and return a set of different states. - const ValueState*::BufferTy& SetRVal(ValueState* St, Expr* Ex, - const RVal::BufferTy& V, - ValueState*::BufferTy& RetBuf); -#endif + ValueState* SetBlkExprRVal(ValueState* St, Expr* Ex, RVal V); ValueState* SetRVal(ValueState* St, LVal LV, RVal V); diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h index eb632ed405..dd99a2ee79 100644 --- a/include/clang/Analysis/PathSensitive/RValues.h +++ b/include/clang/Analysis/PathSensitive/RValues.h @@ -90,6 +90,8 @@ public: symbol_iterator symbol_begin() const; symbol_iterator symbol_end() const; + static RVal MakeVal(BasicValueFactory& BasicVals, DeclRefExpr* E); + // Implement isa<T> support. static inline bool classof(const RVal*) { return true; } }; |