From 38f7bb779854c3812ddd98cae4032788fa2722c4 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 31 May 2018 18:30:41 +0000 Subject: [PATCH] [analyzer] Annotate ProgramState update methods with LLVM_NODISCARD. Because our program states are immutable, methods like "add<>", "set<>", "bind" create a copy of the program state instead of mutating the existing state. If the updated state is discarded, it clearly indicates a bug. Such bugs are introduced frequently, hence the warn_unused_result annotation. Differential Revision: https://reviews.llvm.org/D47499 llvm-svn: 333679 --- .../Core/PathSensitive/ProgramState.h | 117 ++++++++++-------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 6d562e399603..17ab7379fdba 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -177,20 +177,20 @@ public: /// /// This returns a new state with the added constraint on \p cond. /// If no new state is feasible, NULL is returned. - ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const; + LLVM_NODISCARD ProgramStateRef assume(DefinedOrUnknownSVal cond, + bool assumption) const; /// Assumes both "true" and "false" for \p cond, and returns both /// corresponding states (respectively). /// /// This is more efficient than calling assume() twice. Note that one (but not /// both) of the returned states may be NULL. - std::pair + LLVM_NODISCARD std::pair assume(DefinedOrUnknownSVal cond) const; - ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx, - DefinedOrUnknownSVal upperBound, - bool assumption, - QualType IndexType = QualType()) const; + LLVM_NODISCARD ProgramStateRef + assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, + bool assumption, QualType IndexType = QualType()) const; /// Assumes that the value of \p Val is bounded with [\p From; \p To] /// (if \p assumption is "true") or it is fully out of this range @@ -198,17 +198,17 @@ public: /// /// This returns a new state with the added constraint on \p cond. /// If no new state is feasible, NULL is returned. - ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, - const llvm::APSInt &From, - const llvm::APSInt &To, - bool assumption) const; + LLVM_NODISCARD ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool assumption) const; /// Assumes given range both "true" and "false" for \p Val, and returns both /// corresponding states (respectively). /// /// This is more efficient than calling assume() twice. Note that one (but not /// both) of the returned states may be NULL. - std::pair + LLVM_NODISCARD std::pair assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To) const; @@ -232,15 +232,16 @@ public: /// Create a new state by binding the value 'V' to the statement 'S' in the /// state's environment. - ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx, - SVal V, bool Invalidate = true) const; + LLVM_NODISCARD ProgramStateRef BindExpr(const Stmt *S, + const LocationContext *LCtx, SVal V, + bool Invalidate = true) const; - ProgramStateRef bindLoc(Loc location, - SVal V, - const LocationContext *LCtx, - bool notifyChanges = true) const; + LLVM_NODISCARD ProgramStateRef bindLoc(Loc location, SVal V, + const LocationContext *LCtx, + bool notifyChanges = true) const; - ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const; + LLVM_NODISCARD ProgramStateRef bindLoc(SVal location, SVal V, + const LocationContext *LCtx) const; /// Initializes the region of memory represented by \p loc with an initial /// value. Once initialized, all values loaded from any sub-regions of that @@ -248,14 +249,15 @@ public: /// This method should not be used on regions that are already initialized. /// If you need to indicate that memory contents have suddenly become unknown /// within a certain region of memory, consider invalidateRegions(). - ProgramStateRef bindDefaultInitial(SVal loc, SVal V, - const LocationContext *LCtx) const; + LLVM_NODISCARD ProgramStateRef + bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const; /// Performs C++ zero-initialization procedure on the region of memory /// represented by \p loc. - ProgramStateRef bindDefaultZero(SVal loc, const LocationContext *LCtx) const; + LLVM_NODISCARD ProgramStateRef + bindDefaultZero(SVal loc, const LocationContext *LCtx) const; - ProgramStateRef killBinding(Loc LV) const; + LLVM_NODISCARD ProgramStateRef killBinding(Loc LV) const; /// Returns the state with bindings for the given regions /// cleared from the store. @@ -275,14 +277,14 @@ public: /// the call and should be considered directly invalidated. /// \param ITraits information about special handling for a particular /// region/symbol. - ProgramStateRef + LLVM_NODISCARD ProgramStateRef invalidateRegions(ArrayRef Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, const CallEvent *Call = nullptr, RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; - ProgramStateRef + LLVM_NODISCARD ProgramStateRef invalidateRegions(ArrayRef Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, @@ -291,8 +293,8 @@ public: /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. - ProgramStateRef enterStackFrame(const CallEvent &Call, - const StackFrameContext *CalleeCtx) const; + LLVM_NODISCARD ProgramStateRef enterStackFrame( + const CallEvent &Call, const StackFrameContext *CalleeCtx) const; /// Get the lvalue for a base class object reference. Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const; @@ -370,27 +372,29 @@ public: const MemRegion * const *end) const; /// Create a new state in which the statement is marked as tainted. - ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx, - TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addTaint(const Stmt *S, const LocationContext *LCtx, + TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in which the value is marked as tainted. - ProgramStateRef addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in which the symbol is marked as tainted. - ProgramStateRef addTaint(SymbolRef S, + LLVM_NODISCARD ProgramStateRef addTaint(SymbolRef S, TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in which the region symbol is marked as tainted. - ProgramStateRef addTaint(const MemRegion *R, - TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addTaint(const MemRegion *R, TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in a which a sub-region of a given symbol is tainted. /// This might be necessary when referring to regions that can not have an /// individual symbol, e.g. if they are represented by the default binding of /// a LazyCompoundVal. - ProgramStateRef addPartialTaint(SymbolRef ParentSym, - const SubRegion *SubRegion, - TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addPartialTaint(SymbolRef ParentSym, const SubRegion *SubRegion, + TaintTagType Kind = TaintTagGeneric) const; /// Check if the statement is tainted in the current state. bool isTainted(const Stmt *S, const LocationContext *LCtx, @@ -405,8 +409,9 @@ public: void *const* FindGDM(void *K) const; - template - ProgramStateRef add(typename ProgramStateTrait::key_type K) const; + template + LLVM_NODISCARD ProgramStateRef + add(typename ProgramStateTrait::key_type K) const; template typename ProgramStateTrait::data_type @@ -424,27 +429,31 @@ public: template typename ProgramStateTrait::context_type get_context() const; - - template - ProgramStateRef remove(typename ProgramStateTrait::key_type K) const; - - template - ProgramStateRef remove(typename ProgramStateTrait::key_type K, - typename ProgramStateTrait::context_type C) const; template - ProgramStateRef remove() const; + LLVM_NODISCARD ProgramStateRef + remove(typename ProgramStateTrait::key_type K) const; - template - ProgramStateRef set(typename ProgramStateTrait::data_type D) const; + template + LLVM_NODISCARD ProgramStateRef + remove(typename ProgramStateTrait::key_type K, + typename ProgramStateTrait::context_type C) const; - template - ProgramStateRef set(typename ProgramStateTrait::key_type K, - typename ProgramStateTrait::value_type E) const; + template LLVM_NODISCARD ProgramStateRef remove() const; - template - ProgramStateRef set(typename ProgramStateTrait::key_type K, - typename ProgramStateTrait::value_type E, - typename ProgramStateTrait::context_type C) const; + template + LLVM_NODISCARD ProgramStateRef + set(typename ProgramStateTrait::data_type D) const; + + template + LLVM_NODISCARD ProgramStateRef + set(typename ProgramStateTrait::key_type K, + typename ProgramStateTrait::value_type E) const; + + template + LLVM_NODISCARD ProgramStateRef + set(typename ProgramStateTrait::key_type K, + typename ProgramStateTrait::value_type E, + typename ProgramStateTrait::context_type C) const; template bool contains(typename ProgramStateTrait::key_type key) const {