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 22namespace clang { 23 24class Stmt; 25 26namespace ento { 27 28class SValBuilder; 29class 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. 35class EnvironmentEntry : public std::pair<const Stmt *, 36 const StackFrameContext *> { 37public: 38 EnvironmentEntry(const Stmt *s, const LocationContext *L); 39 40 const Stmt *getStmt() const { return first; } 41 const LocationContext *getLocationContext() const { return second; } 42 43 /// Profile an EnvironmentEntry for inclusion in a FoldingSet. 44 static void Profile(llvm::FoldingSetNodeID &ID, 45 const EnvironmentEntry &E) { 46 ID.AddPointer(E.getStmt()); 47 ID.AddPointer(E.getLocationContext()); 48 } 49 50 void Profile(llvm::FoldingSetNodeID &ID) const { 51 Profile(ID, *this); 52 } 53}; 54 55/// An immutable map from EnvironemntEntries to SVals. 56class Environment { 57private: 58 friend class EnvironmentManager; 59 60 using BindingsTy = llvm::ImmutableMap<EnvironmentEntry, SVal>; 61 62 BindingsTy ExprBindings; 63 64 Environment(BindingsTy eb) : ExprBindings(eb) {} 65 66 SVal lookupExpr(const EnvironmentEntry &E) const; 67 68public: 69 using iterator = BindingsTy::iterator; 70 71 iterator begin() const { return ExprBindings.begin(); } 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. 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. 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 99class EnvironmentManager { 100private: 101 using FactoryTy = Environment::BindingsTy::Factory; 102 103 FactoryTy F; 104 105public: 106 EnvironmentManager(llvm::BumpPtrAllocator &Allocator) : F(Allocator) {} 107 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