diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive')
9 files changed, 91 insertions, 71 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 1135b51..2c799c0 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -93,7 +93,7 @@ public: /// Returns the type of the APSInt used to store values of the given QualType. APSIntType getAPSIntType(QualType T) const { - assert(T->isIntegerType() || Loc::isLocType(T)); + assert(T->isIntegralOrEnumerationType() || Loc::isLocType(T)); return APSIntType(Ctx.getTypeSize(T), !T->isSignedIntegerOrEnumerationType()); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index cda1366..0b9762a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -110,10 +110,6 @@ public: StoreManager &getStoreManager() { return Eng.getStoreManager(); } - - const AnalyzerOptions::ConfigTable &getConfig() const { - return Eng.getAnalysisManager().options.Config; - } /// \brief Returns the previous node in the exploded graph, which includes /// the state of the program before the checker ran. Note, checkers should diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index 5211916..edcfc8a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -196,6 +196,10 @@ public: return const_cast<ExplodedNode*>(this)->getFirstPred(); } + const ExplodedNode *getFirstSucc() const { + return succ_empty() ? NULL : *(succ_begin()); + } + // Iterators over successor and predecessor vertices. typedef ExplodedNode* const * succ_iterator; typedef const ExplodedNode* const * const_succ_iterator; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index af2f365..9b4f77d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -37,11 +37,12 @@ class StackFrameContext; namespace ento { +class CodeTextRegion; class MemRegionManager; class MemSpaceRegion; class SValBuilder; +class SymbolicRegion; class VarRegion; -class CodeTextRegion; /// Represent a region's offset within the top level base region. class RegionOffset { @@ -145,6 +146,10 @@ public: const MemRegion *StripCasts(bool StripBaseCasts = true) const; + /// \brief If this is a symbolic region, returns the region. Otherwise, + /// goes up the base chain looking for the first symbolic base region. + const SymbolicRegion *getSymbolicBase() const; + bool hasGlobalsOrParametersStorage() const; bool hasStackStorage() const; @@ -169,6 +174,16 @@ public: /// \brief Print the region for use in diagnostics. virtual void printPretty(raw_ostream &os) const; + /// \brief Returns true if this region's textual representation can be used + /// as part of a larger expression. + virtual bool canPrintPrettyAsExpr() const; + + /// \brief Print the region as expression. + /// + /// When this region represents a subexpression, the method is for printing + /// an expression containing it. + virtual void printPrettyAsExpr(raw_ostream &os) const; + Kind getKind() const { return kind; } template<typename RegionTy> const RegionTy* getAs() const; @@ -874,8 +889,9 @@ public: return R->getKind() == VarRegionKind; } - bool canPrintPretty() const; - void printPretty(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const; + + void printPrettyAsExpr(raw_ostream &os) const; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -937,6 +953,8 @@ public: bool canPrintPretty() const; void printPretty(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const; + void printPrettyAsExpr(raw_ostream &os) const; }; class ObjCIvarRegion : public DeclRegion { @@ -952,8 +970,8 @@ public: const ObjCIvarDecl *getDecl() const; QualType getValueType() const; - bool canPrintPretty() const; - void printPretty(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const; + void printPrettyAsExpr(raw_ostream &os) const; void dumpToStream(raw_ostream &os) const; @@ -1082,6 +1100,10 @@ public: static bool classof(const MemRegion *region) { return region->getKind() == CXXBaseObjectRegionKind; } + + bool canPrintPrettyAsExpr() const; + + void printPrettyAsExpr(raw_ostream &os) const; }; template<typename RegionTy> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 6ea7211..42ef1db 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -201,14 +201,6 @@ public: // Binding and retrieving values to/from the environment and symbolic store. //==---------------------------------------------------------------------==// - /// \brief Create a new state with the specified CompoundLiteral binding. - /// \param CL the compound literal expression (the binding key) - /// \param LC the LocationContext of the binding - /// \param V the value to bind. - ProgramStateRef bindCompoundLiteral(const CompoundLiteralExpr *CL, - const LocationContext *LC, - SVal V) const; - /// 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, @@ -711,7 +703,8 @@ ProgramState::getSValAsScalarOrLoc(const Stmt *S, const LocationContext *LCtx) const { if (const Expr *Ex = dyn_cast<Expr>(S)) { QualType T = Ex->getType(); - if (Ex->isGLValue() || Loc::isLocType(T) || T->isIntegerType()) + if (Ex->isGLValue() || Loc::isLocType(T) || + T->isIntegralOrEnumerationType()) return getSVal(S, LCtx); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index f7e49a3..bbb5688 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -78,7 +78,8 @@ public: // FIXME: Remove the second disjunct when we support symbolic // truncation/extension. return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) || - (Ty1->isIntegerType() && Ty2->isIntegerType())); + (Ty1->isIntegralOrEnumerationType() && + Ty2->isIntegralOrEnumerationType())); } SVal evalCast(SVal val, QualType castTy, QualType originalType); @@ -201,6 +202,12 @@ public: DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy, const LocationContext *locContext); + /// Returns the value of \p E, if it can be determined in a non-path-sensitive + /// manner. + /// + /// If \p E is not a constant or cannot be modeled, returns \c None. + Optional<SVal> getConstantVal(const Expr *E); + NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) { return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals)); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 1c5519e..326e784 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -144,16 +144,24 @@ public: /// Otherwise return 0. const FunctionDecl *getAsFunctionDecl() const; - /// If this SVal is a location (subclasses Loc) and - /// wraps a symbol, return that SymbolRef. Otherwise return 0. - SymbolRef getAsLocSymbol() const; + /// \brief If this SVal is a location and wraps a symbol, return that + /// SymbolRef. Otherwise return 0. + /// + /// Casts are ignored during lookup. + /// \param IncludeBaseRegions The boolean that controls whether the search + /// should continue to the base regions if the region is not symbolic. + SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const; /// Get the symbol in the SVal or its base region. SymbolRef getLocSymbolInBase() const; - /// If this SVal wraps a symbol return that SymbolRef. + /// \brief If this SVal wraps a symbol return that SymbolRef. /// Otherwise, return 0. - SymbolRef getAsSymbol() const; + /// + /// Casts are ignored during lookup. + /// \param IncludeBaseRegions The boolean that controls whether the search + /// should continue to the base regions if the region is not symbolic. + SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const; /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then /// return that expression. Otherwise return NULL. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index bbfd579..b219495 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -76,21 +76,6 @@ public: /// \param L the location whose binding should be removed. virtual StoreRef killBinding(Store ST, Loc L) = 0; - /// \brief Create a new store that binds a value to a compound literal. - /// - /// \param ST The original store whose bindings are the basis for the new - /// store. - /// - /// \param CL The compound literal to bind (the binding key). - /// - /// \param LC The LocationContext for the binding. - /// - /// \param V The value to bind to the compound literal. - virtual StoreRef bindCompoundLiteral(Store ST, - const CompoundLiteralExpr *CL, - const LocationContext *LC, - SVal V) = 0; - /// getInitialStore - Returns the initial "empty" store representing the /// value bindings upon entry to an analyzed function. virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 56afca2..914b2be 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -49,7 +49,10 @@ public: MetadataKind, BEGIN_SYMBOLS = RegionValueKind, END_SYMBOLS = MetadataKind, - SymIntKind, IntSymKind, SymSymKind, CastSymbolKind }; + SymIntKind, IntSymKind, SymSymKind, + BEGIN_BINARYSYMEXPRS = SymIntKind, + END_BINARYSYMEXPRS = SymSymKind, + CastSymbolKind }; private: Kind K; @@ -341,24 +344,39 @@ public: } }; -/// SymIntExpr - Represents symbolic expression like 'x' + 3. -class SymIntExpr : public SymExpr { - const SymExpr *LHS; +/// \brief Represents a symbolic expression involving a binary operator +class BinarySymExpr : public SymExpr { BinaryOperator::Opcode Op; - const llvm::APSInt& RHS; QualType T; -public: - SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t) - : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} +protected: + BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t) + : SymExpr(k), Op(op), T(t) {} +public: // FIXME: We probably need to make this out-of-line to avoid redundant // generation of virtual functions. QualType getType() const { return T; } BinaryOperator::Opcode getOpcode() const { return Op; } + // Implement isa<T> support. + static inline bool classof(const SymExpr *SE) { + Kind k = SE->getKind(); + return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS; + } +}; + +/// \brief Represents a symbolic expression like 'x' + 3. +class SymIntExpr : public BinarySymExpr { + const SymExpr *LHS; + const llvm::APSInt& RHS; + +public: + SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t) + : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {} + virtual void dumpToStream(raw_ostream &os) const; const SymExpr *getLHS() const { return LHS; } @@ -375,7 +393,7 @@ public: } void Profile(llvm::FoldingSetNodeID& ID) { - Profile(ID, LHS, Op, RHS, T); + Profile(ID, LHS, getOpcode(), RHS, getType()); } // Implement isa<T> support. @@ -384,21 +402,15 @@ public: } }; -/// IntSymExpr - Represents symbolic expression like 3 - 'x'. -class IntSymExpr : public SymExpr { +/// \brief Represents a symbolic expression like 3 - 'x'. +class IntSymExpr : public BinarySymExpr { const llvm::APSInt& LHS; - BinaryOperator::Opcode Op; const SymExpr *RHS; - QualType T; public: IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : SymExpr(IntSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} - - QualType getType() const { return T; } - - BinaryOperator::Opcode getOpcode() const { return Op; } + : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {} virtual void dumpToStream(raw_ostream &os) const; @@ -416,7 +428,7 @@ public: } void Profile(llvm::FoldingSetNodeID& ID) { - Profile(ID, LHS, Op, RHS, T); + Profile(ID, LHS, getOpcode(), RHS, getType()); } // Implement isa<T> support. @@ -425,26 +437,19 @@ public: } }; -/// SymSymExpr - Represents symbolic expression like 'x' + 'y'. -class SymSymExpr : public SymExpr { +/// \brief Represents a symbolic expression like 'x' + 'y'. +class SymSymExpr : public BinarySymExpr { const SymExpr *LHS; - BinaryOperator::Opcode Op; const SymExpr *RHS; - QualType T; public: SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} + : BinarySymExpr(SymSymKind, op, t), LHS(lhs), RHS(rhs) {} - BinaryOperator::Opcode getOpcode() const { return Op; } const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } - // FIXME: We probably need to make this out-of-line to avoid redundant - // generation of virtual functions. - QualType getType() const { return T; } - virtual void dumpToStream(raw_ostream &os) const; static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, @@ -457,7 +462,7 @@ public: } void Profile(llvm::FoldingSetNodeID& ID) { - Profile(ID, LHS, Op, RHS, T); + Profile(ID, LHS, getOpcode(), RHS, getType()); } // Implement isa<T> support. |