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