diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
commit | 7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch) | |
tree | c72b9241553fc9966179aba84f90f17bfa9235c3 /include/clang/StaticAnalyzer | |
parent | b52119637f743680a99710ce5fdb6646da2772af (diff) | |
download | src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.tar.gz src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.zip |
Vendor import of clang trunk r300422:vendor/clang/clang-trunk-r300422
Notes
Notes:
svn path=/vendor/clang/dist/; revision=317019
svn path=/vendor/clang/clang-trunk-r300422/; revision=317020; tag=vendor/clang/clang-trunk-r300422
Diffstat (limited to 'include/clang/StaticAnalyzer')
17 files changed, 461 insertions, 181 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 69578910499f..790ba5c121c9 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -45,7 +45,6 @@ def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden; def CplusplusOptIn : Package<"cplusplus">, InPackage<OptIn>; def Valist : Package<"valist">; -def ValistAlpha : Package<"valist">, InPackage<Alpha>, Hidden; def DeadCode : Package<"deadcode">; def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden; @@ -280,6 +279,11 @@ def VirtualCallChecker : Checker<"VirtualCall">, let ParentPackage = CplusplusAlpha in { +def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">, + HelpText<"Method calls on a moved-from object and copying a moved-from " + "object will be reported">, + DescFile<"MisusedMovedObjectChecker.cpp">; + def IteratorPastEndChecker : Checker<"IteratorPastEnd">, HelpText<"Check iterators used past end">, DescFile<"IteratorPastEndChecker.cpp">; @@ -291,7 +295,7 @@ def IteratorPastEndChecker : Checker<"IteratorPastEnd">, // Valist checkers. //===----------------------------------------------------------------------===// -let ParentPackage = ValistAlpha in { +let ParentPackage = Valist in { def UninitializedChecker : Checker<"Uninitialized">, HelpText<"Check for usages of uninitialized (or already released) va_lists.">, @@ -305,7 +309,7 @@ def CopyToSelfChecker : Checker<"CopyToSelf">, HelpText<"Check for va_lists which are copied onto itself.">, DescFile<"ValistChecker.cpp">; -} // end : "alpha.valist" +} // end : "valist" //===----------------------------------------------------------------------===// // Deadcode checkers. diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def index 3355f4b6949c..04bf41bfde4f 100644 --- a/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -22,6 +22,7 @@ ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateR #endif ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) +ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver", CreateZ3ConstraintManager) #ifndef ANALYSIS_DIAGNOSTICS #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index dd7a6c863be0..f9477762c758 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -321,9 +321,11 @@ class RegionChanges { const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> Explicits, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) { - return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, - Explicits, Regions, Call); + return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, + Explicits, Regions, + LCtx, Call); } public: diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 0316c8fb173b..52ed260346bf 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -338,6 +338,7 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call); /// \brief Run checkers when pointers escape. @@ -443,10 +444,11 @@ public: typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, - const InvalidatedSymbols *symbols, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions, - const CallEvent *Call)> + const InvalidatedSymbols *symbols, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, + const CallEvent *Call)> CheckRegionChangesFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 0d1a120c9dd4..fb427f618575 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -20,6 +20,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" namespace clang { namespace ento { @@ -29,8 +30,9 @@ class CompoundValData : public llvm::FoldingSetNode { llvm::ImmutableList<SVal> L; public: - CompoundValData(QualType t, llvm::ImmutableList<SVal> l) - : T(t), L(l) {} + CompoundValData(QualType t, llvm::ImmutableList<SVal> l) : T(t), L(l) { + assert(NonLoc::isCompoundType(t)); + } typedef llvm::ImmutableList<SVal>::iterator iterator; iterator begin() const { return L.begin(); } @@ -47,7 +49,9 @@ class LazyCompoundValData : public llvm::FoldingSetNode { const TypedValueRegion *region; public: LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) - : store(st), region(r) {} + : store(st), region(r) { + assert(NonLoc::isCompoundType(r->getValueType())); + } const void *getStore() const { return store.getStore(); } const TypedValueRegion *getRegion() const { return region; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 89610ef5c17d..fa7ee62ab704 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -55,6 +55,7 @@ class CallEventManager; class CallDescription { friend CallEvent; mutable IdentifierInfo *II; + mutable bool IsLookupDone; StringRef FuncName; unsigned RequiredArgs; @@ -68,7 +69,8 @@ public: /// call. Omit this parameter to match every occurance of call with a given /// name regardless the number of arguments. CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement) - : II(nullptr), FuncName(FuncName), RequiredArgs(RequiredArgs) {} + : II(nullptr), IsLookupDone(false), FuncName(FuncName), + RequiredArgs(RequiredArgs) {} /// \brief Get the name of the function that this object matches. StringRef getFunctionName() const { return FuncName; } @@ -381,7 +383,9 @@ public: // Iterator access to formal parameters and their types. private: - typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun; + struct GetTypeFn { + QualType operator()(ParmVarDecl *PD) const { return PD->getType(); } + }; public: /// Return call's formal parameters. @@ -391,7 +395,7 @@ public: /// correspond with the argument value returned by \c getArgSVal(0). virtual ArrayRef<ParmVarDecl*> parameters() const = 0; - typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, get_type_fun> + typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, GetTypeFn> param_type_iterator; /// Returns an iterator over the types of the call's formal parameters. @@ -400,13 +404,11 @@ public: /// definition because it represents a public interface, and probably has /// more annotations. param_type_iterator param_type_begin() const { - return llvm::map_iterator(parameters().begin(), - get_type_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(parameters().begin(), GetTypeFn()); } /// \sa param_type_begin() param_type_iterator param_type_end() const { - return llvm::map_iterator(parameters().end(), - get_type_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(parameters().end(), GetTypeFn()); } // For debugging purposes only diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 6651382d9e95..c01600d5c969 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -139,6 +139,8 @@ public: return nullptr; } + /// Scan all symbols referenced by the constraints. If the symbol is not + /// alive, remove it. virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) = 0; @@ -182,6 +184,9 @@ std::unique_ptr<ConstraintManager> CreateRangeConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine); +std::unique_ptr<ConstraintManager> +CreateZ3ConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine); + } // end GR namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 591b112d60ac..067d70610868 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -237,7 +237,7 @@ public: const CFGBlock *DstF) override; /// Called by CoreEngine. Used to processing branching behavior - /// at static initalizers. + /// at static initializers. void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext& BuilderCtx, ExplodedNode *Pred, @@ -293,6 +293,7 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) override; /// printState - Called by ProgramStateManager to print checker-specific data. @@ -522,7 +523,9 @@ protected: /// Call PointerEscape callback when a value escapes as a result of bind. ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val) override; + SVal Loc, + SVal Val, + const LocationContext *LCtx) override; /// Call PointerEscape callback when a value escapes as a result of /// region invalidation. /// \param[in] ITraits Specifies invalidation traits for regions/symbols. @@ -618,16 +621,16 @@ private: void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, const CallEvent &Call); - /// If the value of the given expression is a NonLoc, copy it into a new - /// temporary object region, and replace the value of the expression with - /// that. + /// If the value of the given expression \p InitWithAdjustments is a NonLoc, + /// copy it into a new temporary object region, and replace the value of the + /// expression with that. /// - /// If \p ResultE is provided, the new region will be bound to this expression - /// instead of \p E. + /// If \p Result is provided, the new region will be bound to this expression + /// instead of \p InitWithAdjustments. ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, const LocationContext *LC, - const Expr *E, - const Expr *ResultE = nullptr); + const Expr *InitWithAdjustments, + const Expr *Result = nullptr); /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG /// block to find the constructor expression that directly constructed into diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index da4b964424c3..29b1c4cdca04 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -182,6 +182,7 @@ protected: MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) { assert(classof(this)); + assert(mgr); } MemRegionManager* getMemRegionManager() const override { return Mgr; } @@ -215,9 +216,12 @@ public: class GlobalsSpaceRegion : public MemSpaceRegion { virtual void anchor(); + protected: - GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) - : MemSpaceRegion(mgr, k) {} + GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) { + assert(classof(this)); + } + public: static bool classof(const MemRegion *R) { Kind k = R->getKind(); @@ -236,7 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { const CodeTextRegion *CR; StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr) - : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {} + : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) { + assert(cr); + } public: void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -257,9 +263,13 @@ public: /// RegionStoreManager::invalidateRegions (instead of finding all the dependent /// globals, we invalidate the whole parent region). class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { + virtual void anchor() override; + protected: NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) - : GlobalsSpaceRegion(mgr, k) {} + : GlobalsSpaceRegion(mgr, k) { + assert(classof(this)); + } public: @@ -326,7 +336,6 @@ public: }; class HeapSpaceRegion : public MemSpaceRegion { - virtual void anchor(); friend class MemRegionManager; HeapSpaceRegion(MemRegionManager *mgr) @@ -341,10 +350,10 @@ public: }; class UnknownSpaceRegion : public MemSpaceRegion { - virtual void anchor(); friend class MemRegionManager; UnknownSpaceRegion(MemRegionManager *mgr) - : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} + : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} + public: void dumpToStream(raw_ostream &os) const override; @@ -355,13 +364,15 @@ public: }; class StackSpaceRegion : public MemSpaceRegion { -private: + virtual void anchor(); + const StackFrameContext *SFC; protected: StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) : MemSpaceRegion(mgr, k), SFC(sfc) { assert(classof(this)); + assert(sfc); } public: @@ -376,7 +387,6 @@ public: }; class StackLocalsSpaceRegion : public StackSpaceRegion { - virtual void anchor(); friend class MemRegionManager; StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} @@ -391,7 +401,6 @@ public: class StackArgumentsSpaceRegion : public StackSpaceRegion { private: - virtual void anchor(); friend class MemRegionManager; StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} @@ -408,11 +417,15 @@ public: /// SubRegion - A region that subsets another larger region. Most regions /// are subclasses of SubRegion. class SubRegion : public MemRegion { -private: virtual void anchor(); + protected: const MemRegion* superRegion; - SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {} + SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) { + assert(classof(this)); + assert(sReg); + } + public: const MemRegion* getSuperRegion() const { return superRegion; @@ -440,13 +453,18 @@ public: /// by a call to 'alloca'. class AllocaRegion : public SubRegion { friend class MemRegionManager; -protected: + unsigned Cnt; // Block counter. Used to distinguish different pieces of // memory allocated by alloca at the same call site. const Expr *Ex; - AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion) - : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {} + AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion) + : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) { + assert(Ex); + } + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, + unsigned Cnt, const MemRegion *superRegion); public: @@ -458,9 +476,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, - unsigned Cnt, const MemRegion *superRegion); - void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { @@ -470,10 +485,12 @@ public: /// TypedRegion - An abstract class representing regions that are typed. class TypedRegion : public SubRegion { -public: - void anchor() override; + virtual void anchor() override; + protected: - TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} + TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) { + assert(classof(this)); + } public: virtual QualType getLocationType() const = 0; @@ -492,10 +509,12 @@ public: /// TypedValueRegion - An abstract class representing regions having a typed value. class TypedValueRegion : public TypedRegion { -public: - void anchor() override; + virtual void anchor() override; + protected: - TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {} + TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) { + assert(classof(this)); + } public: virtual QualType getValueType() const = 0; @@ -524,10 +543,13 @@ public: class CodeTextRegion : public TypedRegion { -public: - void anchor() override; + virtual void anchor() override; + protected: - CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} + CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) { + assert(classof(this)); + } + public: bool isBoundable() const override { return false; } @@ -539,13 +561,19 @@ public: /// FunctionCodeRegion - A region that represents code texts of function. class FunctionCodeRegion : public CodeTextRegion { + friend class MemRegionManager; + const NamedDecl *FD; -public: - FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg) + + FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg) : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); } + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, + const MemRegion*); + +public: QualType getLocationType() const override { const ASTContext &Ctx = getContext(); if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) { @@ -568,9 +596,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, - const MemRegion*); - static bool classof(const MemRegion* R) { return R->getKind() == FunctionCodeRegionKind; } @@ -591,8 +616,16 @@ class BlockCodeRegion : public CodeTextRegion { CanQualType locTy; BlockCodeRegion(const BlockDecl *bd, CanQualType lTy, - AnalysisDeclContext *ac, const MemRegion* sreg) - : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {} + AnalysisDeclContext *ac, const CodeSpaceRegion* sreg) + : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) { + assert(bd); + assert(ac); + assert(lTy->getTypePtr()->isBlockPointerType()); + } + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, + CanQualType, const AnalysisDeclContext*, + const MemRegion*); public: QualType getLocationType() const override { @@ -609,10 +642,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, - CanQualType, const AnalysisDeclContext*, - const MemRegion*); - static bool classof(const MemRegion* R) { return R->getKind() == BlockCodeRegionKind; } @@ -626,6 +655,7 @@ public: /// variables. class BlockDataRegion : public TypedRegion { friend class MemRegionManager; + const BlockCodeRegion *BC; const LocationContext *LC; // Can be null */ unsigned BlockCount; @@ -633,10 +663,19 @@ class BlockDataRegion : public TypedRegion { void *OriginalVars; BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, - unsigned count, const MemRegion *sreg) - : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), - BlockCount(count), - ReferencedVars(nullptr), OriginalVars(nullptr) {} + unsigned count, const MemSpaceRegion *sreg) + : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), + BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) { + assert(bc); + assert(lc); + assert(isa<GlobalImmutableSpaceRegion>(sreg) || + isa<StackLocalsSpaceRegion>(sreg) || + isa<UnknownSpaceRegion>(sreg)); + } + + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *, + const LocationContext *, unsigned, + const MemRegion *); public: const BlockCodeRegion *getCodeRegion() const { return BC; } @@ -686,10 +725,6 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const override; - static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *, - const LocationContext *, unsigned, - const MemRegion *); - static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; } @@ -705,13 +740,20 @@ private: /// map the concept of symbolic values into the domain of regions. Symbolic /// regions do not need to be typed. class SymbolicRegion : public SubRegion { -protected: + friend class MemRegionManager; + const SymbolRef sym; -public: - SymbolicRegion(const SymbolRef s, const MemRegion* sreg) - : SubRegion(sreg, SymbolicRegionKind), sym(s) {} + SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg) + : SubRegion(sreg, SymbolicRegionKind), sym(s) { + assert(s); + assert(s->getType()->isAnyPointerType() || + s->getType()->isReferenceType() || + s->getType()->isBlockPointerType()); + assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg)); + } +public: SymbolRef getSymbol() const { return sym; } @@ -736,11 +778,13 @@ public: /// StringRegion - Region associated with a StringLiteral. class StringRegion : public TypedValueRegion { friend class MemRegionManager; + const StringLiteral* Str; -protected: - StringRegion(const StringLiteral* str, const MemRegion* sreg) - : TypedValueRegion(sreg, StringRegionKind), Str(str) {} + StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg) + : TypedValueRegion(sreg, StringRegionKind), Str(str) { + assert(str); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const StringLiteral* Str, @@ -772,12 +816,15 @@ public: /// The region associated with an ObjCStringLiteral. class ObjCStringRegion : public TypedValueRegion { friend class MemRegionManager; + const ObjCStringLiteral* Str; -protected: - - ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg) - : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {} - + + ObjCStringRegion(const ObjCStringLiteral *str, + const GlobalInternalSpaceRegion *sreg) + : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) { + assert(str); + } + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCStringLiteral* Str, const MemRegion* superRegion); @@ -807,12 +854,17 @@ public: /// Compound literals are essentially temporaries that are stack allocated /// or in the global constant pool. class CompoundLiteralRegion : public TypedValueRegion { -private: friend class MemRegionManager; + const CompoundLiteralExpr *CL; - CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg) - : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {} + CompoundLiteralRegion(const CompoundLiteralExpr *cl, + const MemSpaceRegion *sReg) + : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) { + assert(cl); + assert(isa<GlobalInternalSpaceRegion>(sReg) || + isa<StackLocalsSpaceRegion>(sReg)); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const CompoundLiteralExpr *CL, @@ -839,8 +891,11 @@ class DeclRegion : public TypedValueRegion { protected: const Decl *D; - DeclRegion(const Decl *d, const MemRegion* sReg, Kind k) - : TypedValueRegion(sReg, k), D(d) {} + DeclRegion(const Decl *d, const MemRegion *sReg, Kind k) + : TypedValueRegion(sReg, k), D(d) { + assert(classof(this)); + assert(d); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, const MemRegion* superRegion, Kind k); @@ -859,17 +914,24 @@ class VarRegion : public DeclRegion { friend class MemRegionManager; // Constructors and private methods. - VarRegion(const VarDecl *vd, const MemRegion* sReg) - : DeclRegion(vd, sReg, VarRegionKind) {} + VarRegion(const VarDecl *vd, const MemRegion *sReg) + : DeclRegion(vd, sReg, VarRegionKind) { + // VarRegion appears in unknown space when it's a block variable as seen + // from a block using it, when this block is analyzed at top-level. + // Other block variables appear within block data regions, + // which, unlike everything else on this list, are not memory spaces. + assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) || + isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg)); + } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD, const MemRegion *superRegion) { DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); } +public: void Profile(llvm::FoldingSetNodeID& ID) const override; -public: const VarDecl *getDecl() const { return cast<VarDecl>(D); } const StackFrameContext *getStackFrame() const; @@ -895,17 +957,19 @@ public: /// referred to by 'this', but rather 'this' itself. class CXXThisRegion : public TypedValueRegion { friend class MemRegionManager; + CXXThisRegion(const PointerType *thisPointerTy, - const MemRegion *sReg) - : TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {} + const StackArgumentsSpaceRegion *sReg) + : TypedValueRegion(sReg, CXXThisRegionKind), + ThisPointerTy(thisPointerTy) {} static void ProfileRegion(llvm::FoldingSetNodeID &ID, const PointerType *PT, const MemRegion *sReg); +public: void Profile(llvm::FoldingSetNodeID &ID) const override; -public: QualType getValueType() const override { return QualType(ThisPointerTy, 0); } @@ -923,9 +987,14 @@ private: class FieldRegion : public DeclRegion { friend class MemRegionManager; - FieldRegion(const FieldDecl *fd, const MemRegion* sReg) + FieldRegion(const FieldDecl *fd, const SubRegion* sReg) : DeclRegion(fd, sReg, FieldRegionKind) {} + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, + const MemRegion* superRegion) { + DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); + } + public: const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } @@ -936,11 +1005,6 @@ public: DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, - const MemRegion* superRegion) { - DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); - } - static bool classof(const MemRegion* R) { return R->getKind() == FieldRegionKind; } @@ -954,10 +1018,9 @@ public: }; class ObjCIvarRegion : public DeclRegion { - friend class MemRegionManager; - ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg); + ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg); static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd, const MemRegion* superRegion); @@ -982,7 +1045,6 @@ public: class ElementRegion; class RegionRawOffset { -private: friend class ElementRegion; const MemRegion *Region; @@ -1007,9 +1069,9 @@ class ElementRegion : public TypedValueRegion { QualType ElementType; NonLoc Index; - ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg) - : TypedValueRegion(sReg, ElementRegionKind), - ElementType(elementType), Index(Idx) { + ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg) + : TypedValueRegion(sReg, ElementRegionKind), + ElementType(elementType), Index(Idx) { assert((!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && "The index must be signed"); @@ -1047,12 +1109,16 @@ class CXXTempObjectRegion : public TypedValueRegion { Expr const *Ex; - CXXTempObjectRegion(Expr const *E, MemRegion const *sReg) - : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {} + CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg) + : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) { + assert(E); + assert(isa<StackLocalsSpaceRegion>(sReg) || + isa<GlobalInternalSpaceRegion>(sReg)); + } static void ProfileRegion(llvm::FoldingSetNodeID &ID, Expr const *E, const MemRegion *sReg); - + public: const Expr *getExpr() const { return Ex; } @@ -1077,8 +1143,10 @@ class CXXBaseObjectRegion : public TypedValueRegion { llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data; CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual, - const MemRegion *SReg) - : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {} + const SubRegion *SReg) + : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) { + assert(RD); + } static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD, bool IsVirtual, const MemRegion *SReg); @@ -1204,16 +1272,16 @@ public: /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and super region. - const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR); - + const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR); + /// getElementRegion - Retrieve the memory region associated with the /// associated element type, index, and super region. const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx, - const MemRegion *superRegion, + const SubRegion *superRegion, ASTContext &Ctx); const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, - const MemRegion *superRegion) { + const SubRegion *superRegion) { return getElementRegion(ER->getElementType(), ER->getIndex(), superRegion, ER->getContext()); } @@ -1223,10 +1291,10 @@ public: /// memory region (which typically represents the memory representing /// a structure or class). const FieldRegion *getFieldRegion(const FieldDecl *fd, - const MemRegion* superRegion); + const SubRegion* superRegion); const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, - const MemRegion *superRegion) { + const SubRegion *superRegion) { return getFieldRegion(FR->getDecl(), superRegion); } @@ -1235,7 +1303,7 @@ public: /// to the containing region (which typically represents the Objective-C /// object). const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd, - const MemRegion* superRegion); + const SubRegion* superRegion); const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC); @@ -1245,14 +1313,14 @@ public: /// /// The type of \p Super is assumed be a class deriving from \p BaseClass. const CXXBaseObjectRegion * - getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super, + getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, bool IsVirtual); /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different /// super region. const CXXBaseObjectRegion * getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg, - const MemRegion *superRegion) { + const SubRegion *superRegion) { return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion, baseReg->isVirtual()); } @@ -1276,17 +1344,22 @@ public: const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex); private: - template <typename RegionTy, typename A1> - RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion); - - template <typename RegionTy, typename A1, typename A2> - RegionTy* getSubRegion(const A1 a1, const A2 a2, - const MemRegion* superRegion); + template <typename RegionTy, typename SuperTy, + typename Arg1Ty> + RegionTy* getSubRegion(const Arg1Ty arg1, + const SuperTy* superRegion); + + template <typename RegionTy, typename SuperTy, + typename Arg1Ty, typename Arg2Ty> + RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, + const SuperTy* superRegion); + + template <typename RegionTy, typename SuperTy, + typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> + RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, + const Arg3Ty arg3, + const SuperTy* superRegion); - template <typename RegionTy, typename A1, typename A2, typename A3> - RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3, - const MemRegion* superRegion); - template <typename REG> const REG* LazyAllocate(REG*& region); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 463b375fda30..2910ef4212cc 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -229,11 +229,12 @@ public: ProgramStateRef bindLoc(Loc location, SVal V, + const LocationContext *LCtx, bool notifyChanges = true) const; - ProgramStateRef bindLoc(SVal location, SVal V) const; + ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const; - ProgramStateRef bindDefault(SVal loc, SVal V) const; + ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const; ProgramStateRef killBinding(Loc LV) const; @@ -681,9 +682,9 @@ ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val, this, Val.castAs<NonLoc>(), From, To); } -inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { +inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const { if (Optional<Loc> L = LV.getAs<Loc>()) - return bindLoc(*L, V); + return bindLoc(*L, V, LCtx); return this; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index a4c01fc45334..14aa3af37620 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -112,6 +112,11 @@ public: /// Evaluates a given SVal. If the SVal has only one possible (integer) value, /// that value is returned. Otherwise, returns NULL. virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0; + + /// Simplify symbolic expressions within a given SVal. Return an SVal + /// that represents the same value, but is hopefully easier to work with + /// than the original SVal. + virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0; /// Constructs a symbolic expression for two non-location values. SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index cc3c02a02c64..935f0018324a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -41,6 +41,22 @@ class MemRegionManager; class ProgramStateManager; class SValBuilder; +namespace nonloc { +/// Sub-kinds for NonLoc values. +enum Kind { +#define NONLOC_SVAL(Id, Parent) Id ## Kind, +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" +}; +} + +namespace loc { +/// Sub-kinds for Loc values. +enum Kind { +#define LOC_SVAL(Id, Parent) Id ## Kind, +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" +}; +} + /// SVal - This represents a symbolic expression, which can be either /// an L-value or an R-value. /// @@ -75,10 +91,7 @@ public: template<typename T> T castAs() const { assert(T::isKind(*this)); - T t; - SVal& sv = t; - sv = *this; - return t; + return *static_cast<const T *>(this); } /// \brief Convert to the specified SVal type, returning None if this SVal is @@ -87,10 +100,7 @@ public: Optional<T> getAs() const { if (!T::isKind(*this)) return None; - T t; - SVal& sv = t; - sv = *this; - return t; + return *static_cast<const T *>(this); } /// BufferTy - A temporary buffer to hold a set of SVals. @@ -273,6 +283,11 @@ protected: public: void dumpToStream(raw_ostream &Out) const; + static inline bool isCompoundType(QualType T) { + return T->isArrayType() || T->isRecordType() || + T->isComplexType() || T->isVectorType(); + } + private: friend class SVal; static bool isKind(const SVal& V) { @@ -307,15 +322,11 @@ private: namespace nonloc { -enum Kind { -#define NONLOC_SVAL(Id, Parent) Id ## Kind, -#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" -}; - /// \brief Represents symbolic expression. class SymbolVal : public NonLoc { public: - SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} + SymbolVal() = delete; + SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); } SymbolRef getSymbol() const { return (const SymExpr*) Data; @@ -327,7 +338,6 @@ public: private: friend class SVal; - SymbolVal() {} static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == SymbolValKind; @@ -373,7 +383,11 @@ class LocAsInteger : public NonLoc { explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) : NonLoc(LocAsIntegerKind, &data) { - assert (data.first.getAs<Loc>()); + // We do not need to represent loc::ConcreteInt as LocAsInteger, + // as it'd collapse into a nonloc::ConcreteInt instead. + assert(data.first.getBaseKind() == LocKind && + (data.first.getSubKind() == loc::MemRegionValKind || + data.first.getSubKind() == loc::GotoLabelKind)); } public: @@ -513,14 +527,11 @@ private: namespace loc { -enum Kind { -#define LOC_SVAL(Id, Parent) Id ## Kind, -#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" -}; - class GotoLabel : public Loc { public: - explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {} + explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) { + assert(Label); + } const LabelDecl *getLabel() const { return static_cast<const LabelDecl*>(Data); @@ -541,7 +552,9 @@ private: class MemRegionVal : public Loc { public: - explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {} + explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) { + assert(r); + } /// \brief Get the underlining region. const MemRegion* getRegion() const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h new file mode 100644 index 000000000000..2c9802bbc536 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h @@ -0,0 +1,92 @@ +//== SimpleConstraintManager.h ----------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Simplified constraint manager backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SIMPLECONSTRAINTMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SIMPLECONSTRAINTMANAGER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" + +namespace clang { + +namespace ento { + +class SimpleConstraintManager : public ConstraintManager { + SubEngine *SU; + SValBuilder &SVB; + +public: + SimpleConstraintManager(SubEngine *subengine, SValBuilder &SB) + : SU(subengine), SVB(SB) {} + + ~SimpleConstraintManager() override; + + //===------------------------------------------------------------------===// + // Implementation for interface from ConstraintManager. + //===------------------------------------------------------------------===// + + /// Ensures that the DefinedSVal conditional is expressed as a NonLoc by + /// creating boolean casts to handle Loc's. + ProgramStateRef assume(ProgramStateRef State, DefinedSVal Cond, + bool Assumption) override; + + ProgramStateRef assumeInclusiveRange(ProgramStateRef State, NonLoc Value, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) override; + +protected: + //===------------------------------------------------------------------===// + // Interface that subclasses must implement. + //===------------------------------------------------------------------===// + + /// Given a symbolic expression that can be reasoned about, assume that it is + /// true/false and generate the new program state. + virtual ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym, + bool Assumption) = 0; + + /// Given a symbolic expression within the range [From, To], assume that it is + /// true/false and generate the new program state. + /// This function is used to handle case ranges produced by a language + /// extension for switch case statements. + virtual ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, + SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) = 0; + + /// Given a symbolic expression that cannot be reasoned about, assume that + /// it is zero/nonzero and add it directly to the solver state. + virtual ProgramStateRef assumeSymUnsupported(ProgramStateRef State, + SymbolRef Sym, + bool Assumption) = 0; + + //===------------------------------------------------------------------===// + // Internal implementation. + //===------------------------------------------------------------------===// + + BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); } + SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); } + +private: + ProgramStateRef assume(ProgramStateRef State, NonLoc Cond, bool Assumption); + + ProgramStateRef assumeAux(ProgramStateRef State, NonLoc Cond, + bool Assumption); +}; + +} // end GR namespace + +} // end clang namespace + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index fa7d3f72abf1..7619f22f4013 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -59,6 +59,30 @@ public: /// \return The value bound to the location \c loc. virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0; + /// Return the default value bound to a region in a given store. The default + /// binding is the value of sub-regions that were not initialized separately + /// from their base region. For example, if the structure is zero-initialized + /// upon construction, this method retrieves the concrete zero value, even if + /// some or all fields were later overwritten manually. Default binding may be + /// an unknown, undefined, concrete, or symbolic value. + /// \param[in] store The store in which to make the lookup. + /// \param[in] R The region to find the default binding for. + /// \return The default value bound to the region in the store, if a default + /// binding exists. + virtual Optional<SVal> getDefaultBinding(Store store, const MemRegion *R) = 0; + + /// Return the default value bound to a LazyCompoundVal. The default binding + /// is used to represent the value of any fields or elements within the + /// structure represented by the LazyCompoundVal which were not initialized + /// explicitly separately from the whole structure. Default binding may be an + /// unknown, undefined, concrete, or symbolic value. + /// \param[in] lcv The lazy compound value. + /// \return The default value bound to the LazyCompoundVal \c lcv, if a + /// default binding exists. + Optional<SVal> getDefaultBinding(nonloc::LazyCompoundVal lcv) { + return getDefaultBinding(lcv.getStore(), lcv.getRegion()); + } + /// Return a state with the specified value bound to the given location. /// \param[in] store The analysis state. /// \param[in] loc The symbolic memory location. @@ -136,7 +160,7 @@ public: /// valid only if Failed flag is set to false. SVal attemptDownCast(SVal Base, QualType DerivedPtrType, bool &Failed); - const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); + const ElementRegion *GetElementZeroRegion(const SubRegion *R, QualType T); /// castRegion - Used by ExprEngine::VisitCast to handle casts from /// a MemRegion* to a specific location type. 'R' is the region being @@ -235,8 +259,9 @@ public: virtual void iterBindings(Store store, BindingsHandler& f) = 0; protected: - const MemRegion *MakeElementRegion(const MemRegion *baseRegion, - QualType pointeeTy, uint64_t index = 0); + const ElementRegion *MakeElementRegion(const SubRegion *baseRegion, + QualType pointeeTy, + uint64_t index = 0); /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 581ef206cff3..8ccd34751bbe 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -83,7 +83,7 @@ public: const CFGBlock *DstF) = 0; /// Called by CoreEngine. Used to processing branching behavior - /// at static initalizers. + /// at static initializers. virtual void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext& BuilderCtx, ExplodedNode *Pred, @@ -131,17 +131,19 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) = 0; inline ProgramStateRef processRegionChange(ProgramStateRef state, - const MemRegion* MR) { - return processRegionChanges(state, nullptr, MR, MR, nullptr); + const MemRegion* MR, + const LocationContext *LCtx) { + return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr); } virtual ProgramStateRef - processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0; + processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0; virtual ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index 18bc60754b81..f72033955ec3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -42,6 +42,12 @@ private: protected: SymExpr(Kind k) : K(k) {} + static bool isValidTypeForSymbol(QualType T) { + // FIXME: Depending on whether we choose to deprecate structural symbols, + // this may become much stricter. + return !T.isNull() && !T->isVoidType(); + } + public: virtual ~SymExpr() {} @@ -103,7 +109,9 @@ class SymbolData : public SymExpr { const SymbolID Sym; protected: - SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {} + SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) { + assert(classof(this)); + } public: ~SymbolData() override {} diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index f00dce568e3a..e9701142cd9e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -44,7 +44,10 @@ class SymbolRegionValue : public SymbolData { public: SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) - : SymbolData(SymbolRegionValueKind, sym), R(r) {} + : SymbolData(SymbolRegionValueKind, sym), R(r) { + assert(r); + assert(isValidTypeForSymbol(r->getValueType())); + } const TypedValueRegion* getRegion() const { return R; } @@ -81,7 +84,15 @@ public: SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, QualType t, unsigned count, const void *symbolTag) : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count), - LCtx(lctx), SymbolTag(symbolTag) {} + LCtx(lctx), SymbolTag(symbolTag) { + // FIXME: 's' might be a nullptr if we're conducting invalidation + // that was caused by a destructor call on a temporary object, + // which has no statement associated with it. + // Due to this, we might be creating the same invalidation symbol for + // two different invalidation passes (for two different temporaries). + assert(lctx); + assert(isValidTypeForSymbol(t)); + } const Stmt *getStmt() const { return S; } unsigned getCount() const { return Count; } @@ -120,7 +131,11 @@ class SymbolDerived : public SymbolData { public: SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) - : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {} + : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) { + assert(parent); + assert(r); + assert(isValidTypeForSymbol(r->getValueType())); + } SymbolRef getParentSymbol() const { return parentSymbol; } const TypedValueRegion *getRegion() const { return R; } @@ -155,7 +170,9 @@ class SymbolExtent : public SymbolData { public: SymbolExtent(SymbolID sym, const SubRegion *r) - : SymbolData(SymbolExtentKind, sym), R(r) {} + : SymbolData(SymbolExtentKind, sym), R(r) { + assert(r); + } const SubRegion *getRegion() const { return R; } @@ -193,7 +210,13 @@ public: SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, const LocationContext *LCtx, unsigned count, const void *tag) : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), - Count(count), Tag(tag) {} + Count(count), Tag(tag) { + assert(r); + assert(s); + assert(isValidTypeForSymbol(t)); + assert(LCtx); + assert(tag); + } const MemRegion *getRegion() const { return R; } const Stmt *getStmt() const { return S; } @@ -236,8 +259,13 @@ class SymbolCast : public SymExpr { QualType ToTy; public: - SymbolCast(const SymExpr *In, QualType From, QualType To) : - SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { } + SymbolCast(const SymExpr *In, QualType From, QualType To) + : SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { + assert(In); + assert(isValidTypeForSymbol(From)); + // FIXME: GenericTaintChecker creates symbols of void type. + // Otherwise, 'To' should also be a valid type. + } QualType getType() const override { return ToTy; } @@ -270,7 +298,10 @@ class BinarySymExpr : public SymExpr { protected: BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t) - : SymExpr(k), Op(op), T(t) {} + : SymExpr(k), Op(op), T(t) { + assert(classof(this)); + assert(isValidTypeForSymbol(t)); + } public: // FIXME: We probably need to make this out-of-line to avoid redundant @@ -293,8 +324,10 @@ class SymIntExpr : public BinarySymExpr { public: SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t) - : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {} + const llvm::APSInt &rhs, QualType t) + : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) { + assert(lhs); + } void dumpToStream(raw_ostream &os) const override; @@ -327,9 +360,11 @@ class IntSymExpr : public BinarySymExpr { const SymExpr *RHS; public: - IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, + IntSymExpr(const llvm::APSInt &lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) { + assert(rhs); + } void dumpToStream(raw_ostream &os) const override; @@ -364,7 +399,10 @@ class SymSymExpr : public BinarySymExpr { public: SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) - : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {} + : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) { + assert(lhs); + assert(rhs); + } const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } |