diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/RValues.h | 24 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 1 | ||||
-rw-r--r-- | lib/Analysis/GRSimpleVals.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/RValues.cpp | 10 | ||||
-rw-r--r-- | lib/Analysis/ValueState.cpp | 3 | ||||
-rw-r--r-- | test/Analysis/null-deref-ps.c | 9 |
7 files changed, 50 insertions, 3 deletions
diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h index 45a5452ffc..8a53588564 100644 --- a/include/clang/Analysis/PathSensitive/RValues.h +++ b/include/clang/Analysis/PathSensitive/RValues.h @@ -128,7 +128,7 @@ public: static NonLVal MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T); static NonLVal MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I); - + static NonLVal MakeIntTruthVal(BasicValueFactory& BasicVals, bool b); // Implement isa<T> support. @@ -151,6 +151,8 @@ public: static LVal MakeVal(AddrLabelExpr* E); + static LVal MakeVal(StringLiteral* S); + // Implement isa<T> support. static inline bool classof(const RVal* V) { return V->getBaseKind() == LValKind; @@ -274,7 +276,7 @@ public: namespace lval { enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind, - ConcreteIntKind }; + ConcreteIntKind, StringLiteralValKind }; class SymbolVal : public LVal { public: @@ -391,6 +393,24 @@ public: } }; +class StringLiteralVal : public LVal { +public: + StringLiteralVal(StringLiteral* L) : LVal(StringLiteralValKind, L) {} + + StringLiteral* getLiteral() const { return (StringLiteral*) Data; } + + // Implement isa<T> support. + static inline bool classof(const RVal* V) { + return V->getBaseKind() == LValKind && + V->getSubKind() == StringLiteralValKind; + } + + static inline bool classof(const LVal* V) { + return V->getSubKind() == StringLiteralValKind; + } +}; + + } // end clang::lval namespace } // end clang namespace diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 253e00589e..499da2f85f 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -826,6 +826,8 @@ void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst, // should compose behavior, not copy it. StateMgr.Unbind(StVals, cast<LVal>(V)); } + else if (isa<nonlval::LValAsInteger>(V)) + StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal()); } St = StateMgr.getPersistentState(StVals); diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index bdb742929d..128ef82c63 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -2014,6 +2014,7 @@ ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond, case lval::DeclValKind: case lval::FuncValKind: case lval::GotoLabelKind: + case lval::StringLiteralValKind: isFeasible = Assumption; return St; diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 2c14dde08b..e41df7662c 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -572,6 +572,10 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst, if (isa<LVal>(V)) St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal()); + else if (isa<nonlval::LValAsInteger>(V)) + St = StateMgr.SetRVal(St, cast<nonlval::LValAsInteger>(V).getLVal(), + UnknownVal()); + } // Make up a symbol for the return value of this function. diff --git a/lib/Analysis/RValues.cpp b/lib/Analysis/RValues.cpp index 86f5ac96fd..5e161f34a5 100644 --- a/lib/Analysis/RValues.cpp +++ b/lib/Analysis/RValues.cpp @@ -240,6 +240,10 @@ RVal RVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) { LVal LVal::MakeVal(AddrLabelExpr* E) { return lval::GotoLabel(E->getLabel()); } +LVal LVal::MakeVal(StringLiteral* S) { + return lval::StringLiteralVal(S); +} + //===----------------------------------------------------------------------===// // Utility methods for constructing RVals (both NonLVals and LVals). //===----------------------------------------------------------------------===// @@ -392,6 +396,12 @@ void LVal::print(std::ostream& Out) const { << cast<lval::FuncVal>(this)->getDecl()->getIdentifier()->getName(); break; + case lval::StringLiteralValKind: + Out << "literal \"" + << cast<lval::StringLiteralVal>(this)->getLiteral()->getStrData() + << "\""; + break; + default: assert (false && "Pretty-printing not implemented for this LVal."); break; diff --git a/lib/Analysis/ValueState.cpp b/lib/Analysis/ValueState.cpp index bba2e06a18..8027ce9fcb 100644 --- a/lib/Analysis/ValueState.cpp +++ b/lib/Analysis/ValueState.cpp @@ -264,6 +264,9 @@ RVal ValueStateManager::GetRVal(ValueState* St, Expr* E) { case Stmt::IntegerLiteralClass: { return NonLVal::MakeVal(BasicVals, cast<IntegerLiteral>(E)); } + + case Stmt::StringLiteralClass: + return LVal::MakeVal(cast<StringLiteral>(E)); // Casts where the source and target type are the same // are no-ops. We blast through these to get the descendant diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 6d954fd957..2e66e18b66 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -38,4 +38,11 @@ int f4(int *p) { int *q = (int*) x; return *q; // expected-warning{{Dereference of null pointer.}} -}
\ No newline at end of file +} + +int f5() { + + char *s = "hello world"; + return s[0]; // no-warning +} + |