1 //===- Environment.h - Map from Stmt* to Locations/Values -------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defined the Environment and EnvironmentManager classes. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H 15 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H 16 17 #include "clang/Analysis/AnalysisDeclContext.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 20 #include "llvm/ADT/ImmutableMap.h" 21 #include <utility> 22 23 namespace clang { 24 25 class Stmt; 26 27 namespace ento { 28 29 class SValBuilder; 30 class SymbolReaper; 31 32 /// An entry in the environment consists of a Stmt and an LocationContext. 33 /// This allows the environment to manage context-sensitive bindings, 34 /// which is essentially for modeling recursive function analysis, among 35 /// other things. 36 class EnvironmentEntry : public std::pair<const Stmt *, 37 const StackFrameContext *> { 38 public: 39 EnvironmentEntry(const Stmt *s, const LocationContext *L); 40 getStmt()41 const Stmt *getStmt() const { return first; } getLocationContext()42 const LocationContext *getLocationContext() const { return second; } 43 44 /// Profile an EnvironmentEntry for inclusion in a FoldingSet. Profile(llvm::FoldingSetNodeID & ID,const EnvironmentEntry & E)45 static void Profile(llvm::FoldingSetNodeID &ID, 46 const EnvironmentEntry &E) { 47 ID.AddPointer(E.getStmt()); 48 ID.AddPointer(E.getLocationContext()); 49 } 50 Profile(llvm::FoldingSetNodeID & ID)51 void Profile(llvm::FoldingSetNodeID &ID) const { 52 Profile(ID, *this); 53 } 54 }; 55 56 /// An immutable map from EnvironemntEntries to SVals. 57 class Environment { 58 private: 59 friend class EnvironmentManager; 60 61 using BindingsTy = llvm::ImmutableMap<EnvironmentEntry, SVal>; 62 63 BindingsTy ExprBindings; 64 Environment(BindingsTy eb)65 Environment(BindingsTy eb) : ExprBindings(eb) {} 66 67 SVal lookupExpr(const EnvironmentEntry &E) const; 68 69 public: 70 using iterator = BindingsTy::iterator; 71 begin()72 iterator begin() const { return ExprBindings.begin(); } end()73 iterator end() const { return ExprBindings.end(); } 74 75 /// Fetches the current binding of the expression in the 76 /// Environment. 77 SVal getSVal(const EnvironmentEntry &E, SValBuilder &svalBuilder) const; 78 79 /// Profile - Profile the contents of an Environment object for use 80 /// in a FoldingSet. Profile(llvm::FoldingSetNodeID & ID,const Environment * env)81 static void Profile(llvm::FoldingSetNodeID& ID, const Environment* env) { 82 env->ExprBindings.Profile(ID); 83 } 84 85 /// Profile - Used to profile the contents of this object for inclusion 86 /// in a FoldingSet. Profile(llvm::FoldingSetNodeID & ID)87 void Profile(llvm::FoldingSetNodeID& ID) const { 88 Profile(ID, this); 89 } 90 91 bool operator==(const Environment& RHS) const { 92 return ExprBindings == RHS.ExprBindings; 93 } 94 95 void print(raw_ostream &Out, const char *NL, const char *Sep, 96 const ASTContext &Context, 97 const LocationContext *WithLC = nullptr) const; 98 }; 99 100 class EnvironmentManager { 101 private: 102 using FactoryTy = Environment::BindingsTy::Factory; 103 104 FactoryTy F; 105 106 public: EnvironmentManager(llvm::BumpPtrAllocator & Allocator)107 EnvironmentManager(llvm::BumpPtrAllocator &Allocator) : F(Allocator) {} 108 getInitialEnvironment()109 Environment getInitialEnvironment() { 110 return Environment(F.getEmptyMap()); 111 } 112 113 /// Bind a symbolic value to the given environment entry. 114 Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, 115 bool Invalidate); 116 117 Environment removeDeadBindings(Environment Env, 118 SymbolReaper &SymReaper, 119 ProgramStateRef state); 120 }; 121 122 } // namespace ento 123 124 } // namespace clang 125 126 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H 127