Home | History | Annotate | Line # | Download | only in PathSensitive
      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 
     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.
     56 class Environment {
     57 private:
     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 
     68 public:
     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 
     99 class EnvironmentManager {
    100 private:
    101   using FactoryTy = Environment::BindingsTy::Factory;
    102 
    103   FactoryTy F;
    104 
    105 public:
    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