<commit_before>//== BasicStore.cpp - Basic map from Locations to Values --------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defined the BasicStore and BasicStoreManager classes.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/PathSensitive/GRState.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"

using namespace clang;

typedef llvm::ImmutableMap<const VarDecl*,SVal> VarBindingsTy;  

namespace {
  
class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
  VarBindingsTy::Factory VBFactory;
  GRStateManager& StateMgr;
  MemRegionManager MRMgr;
  const MemRegion* SelfRegion;
  
public:
  BasicStoreManager(GRStateManager& mgr)
    : VBFactory(mgr.getAllocator()), 
      StateMgr(mgr), 
      MRMgr(StateMgr.getAllocator()), 
      SelfRegion(0) {}
  
  ~BasicStoreManager() {}

  SVal Retrieve(const GRState *state, Loc LV, QualType T);  
  Store Bind(Store St, Loc LV, SVal V);  
  Store Remove(Store St, Loc LV);
  Store getInitialStore();
  MemRegionManager& getRegionManager() { return MRMgr; }

  // FIXME: Investigate what is using this. This method should be removed.
  virtual Loc getLoc(const VarDecl* VD) {
    return loc::MemRegionVal(MRMgr.getVarRegion(VD));
  }
  
  Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL,
                            SVal V) {
    return store;
  }
  
  SVal getLValueVar(const GRState* St, const VarDecl* VD);
  SVal getLValueString(const GRState* St, const StringLiteral* S);
  SVal getLValueCompoundLiteral(const GRState* St, 
                                const CompoundLiteralExpr* CL);
  SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
  SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);  
  SVal getLValueElement(const GRState* St, SVal Base, SVal Offset);

  /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
  ///  conversions between arrays and pointers.
  SVal ArrayToPointer(SVal Array) { return Array; }

  std::pair<const GRState*, SVal> 
  CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE) {
    return std::make_pair(St, UnknownVal());
  }

  
  /// getSelfRegion - Returns the region for the 'self' (Objective-C) or
  ///  'this' object (C++).  When used when analyzing a normal function this
  ///  method returns NULL.
  const MemRegion* getSelfRegion(Store) { 
    return SelfRegion;  
  }
    
  /// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
  ///  It returns a new Store with these values removed, and populates LSymbols
  ///  and DSymbols with the known set of live and dead symbols respectively.
  Store RemoveDeadBindings(const GRState* state, Stmt* Loc,
                           const LiveVariables& Live,
                           llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
                           LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);

  void iterBindings(Store store, BindingsHandler& f);

  Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);

  static inline VarBindingsTy GetVarBindings(Store store) {
    return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
  }

  void print(Store store, std::ostream& Out, const char* nl, const char *sep);
};
    
} // end anonymous namespace


StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
  return new BasicStoreManager(StMgr);
}

SVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
  return loc::MemRegionVal(MRMgr.getVarRegion(VD));
}

SVal BasicStoreManager::getLValueString(const GRState* St, 
                                        const StringLiteral* S) {
  return loc::MemRegionVal(MRMgr.getStringRegion(S));
}

SVal BasicStoreManager::getLValueCompoundLiteral(const GRState* St,
                                                 const CompoundLiteralExpr* CL){
  return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
}

SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
                                      SVal Base) {
  return UnknownVal();
}
  
  
SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
                                       const FieldDecl* D) {

  if (Base.isUnknownOrUndef())
    return Base;
  
  Loc BaseL = cast<Loc>(Base);  
  const MemRegion* BaseR = 0;
  
  switch(BaseL.getSubKind()) {
    case loc::SymbolValKind:
      BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
      break;
      
    case loc::GotoLabelKind:
    case loc::FuncValKind:
      // Technically we can get here if people do funny things with casts.
      return UndefinedVal();

    case loc::MemRegionKind:
      BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
      break;
      
    case loc::ConcreteIntKind:
      // While these seem funny, this can happen through casts.
      // FIXME: What we should return is the field offset.  For example,
      //  add the field offset to the integer value.  That way funny things
      //  like this work properly:  &(((struct foo *) 0xa)->f)
      return Base;

    default:
      assert ("Unhandled Base.");
      return Base;
  }
  
  return loc::MemRegionVal(MRMgr.getFieldRegion(D, BaseR));
}

SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
                                         SVal Offset) {

  
  if (Base.isUnknownOrUndef())
    return Base;
  
  Loc BaseL = cast<Loc>(Base);  
  const MemRegion* BaseR = 0;
  
  switch(BaseL.getSubKind()) {
    case loc::SymbolValKind:
      BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
      break;
      
    case loc::GotoLabelKind:
    case loc::FuncValKind:
      // Technically we can get here if people do funny things with casts.<commit_msg>Fix to BasicStoreManager::getElementLValue: If the base region is a symbol, layer an AnonTypedRegion on top of it.<commit_after>//== BasicStore.cpp - Basic map from Locations to Values --------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defined the BasicStore and BasicStoreManager classes.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/PathSensitive/GRState.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"

using namespace clang;

typedef llvm::ImmutableMap<const VarDecl*,SVal> VarBindingsTy;  

namespace {
  
class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
  VarBindingsTy::Factory VBFactory;
  GRStateManager& StateMgr;
  MemRegionManager MRMgr;
  const MemRegion* SelfRegion;
  
public:
  BasicStoreManager(GRStateManager& mgr)
    : VBFactory(mgr.getAllocator()), 
      StateMgr(mgr), 
      MRMgr(StateMgr.getAllocator()), 
      SelfRegion(0) {}
  
  ~BasicStoreManager() {}

  SVal Retrieve(const GRState *state, Loc LV, QualType T);  
  Store Bind(Store St, Loc LV, SVal V);  
  Store Remove(Store St, Loc LV);
  Store getInitialStore();
  MemRegionManager& getRegionManager() { return MRMgr; }

  // FIXME: Investigate what is using this. This method should be removed.
  virtual Loc getLoc(const VarDecl* VD) {
    return loc::MemRegionVal(MRMgr.getVarRegion(VD));
  }
  
  Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL,
                            SVal V) {
    return store;
  }
  
  SVal getLValueVar(const GRState* St, const VarDecl* VD);
  SVal getLValueString(const GRState* St, const StringLiteral* S);
  SVal getLValueCompoundLiteral(const GRState* St, 
                                const CompoundLiteralExpr* CL);
  SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
  SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);  
  SVal getLValueElement(const GRState* St, SVal Base, SVal Offset);

  /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
  ///  conversions between arrays and pointers.
  SVal ArrayToPointer(SVal Array) { return Array; }

  std::pair<const GRState*, SVal> 
  CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE) {
    return std::make_pair(St, UnknownVal());
  }

  
  /// getSelfRegion - Returns the region for the 'self' (Objective-C) or
  ///  'this' object (C++).  When used when analyzing a normal function this
  ///  method returns NULL.
  const MemRegion* getSelfRegion(Store) { 
    return SelfRegion;  
  }
    
  /// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
  ///  It returns a new Store with these values removed, and populates LSymbols
  ///  and DSymbols with the known set of live and dead symbols respectively.
  Store RemoveDeadBindings(const GRState* state, Stmt* Loc,
                           const LiveVariables& Live,
                           llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
                           LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);

  void iterBindings(Store store, BindingsHandler& f);

  Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);

  static inline VarBindingsTy GetVarBindings(Store store) {
    return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
  }

  void print(Store store, std::ostream& Out, const char* nl, const char *sep);
};
    
} // end anonymous namespace


StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
  return new BasicStoreManager(StMgr);
}

SVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
  return loc::MemRegionVal(MRMgr.getVarRegion(VD));
}

SVal BasicStoreManager::getLValueString(const GRState* St, 
                                        const StringLiteral* S) {
  return loc::MemRegionVal(MRMgr.getStringRegion(S));
}

SVal BasicStoreManager::getLValueCompoundLiteral(const GRState* St,
                                                 const CompoundLiteralExpr* CL){
  return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
}

SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
                                      SVal Base) {
  return UnknownVal();
}
  
  
SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
                                       const FieldDecl* D) {

  if (Base.isUnknownOrUndef())
    return Base;
  
  Loc BaseL = cast<Loc>(Base);  
  const MemRegion* BaseR = 0;
  
  switch(BaseL.getSubKind()) {
    case loc::SymbolValKind:
      BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
      break;
      
    case loc::GotoLabelKind:
    case loc::FuncValKind:
      // Technically we can get here if people do funny things with casts.
      return UndefinedVal();

    case loc::MemRegionKind:
      BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
      break;
      
    case loc::ConcreteIntKind:
      // While these seem funny, this can happen through casts.
      // FIXME: What we should return is the field offset.  For example,
      //  add the field offset to the integer value.  That way funny things
      //  like this work properly:  &(((struct foo *) 0xa)->f)
      return Base;

    default:
      assert ("Unhandled Base.");
      return Base;
  }
  
  return loc::MemRegionVal(MRMgr.getFieldRegion(D, BaseR));
}

SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
                                         SVal Offset) {

  
  if (Base.isUnknownOrUndef())
    return Base;
  
  Loc BaseL = cast<Loc>(Base);  
  const MemRegion* BaseR = 0;
  
  switch(BaseL.getSubKind()) {
    case loc::SymbolValKind: {
      // FIXME: Should we have symbolic regions be typed or typeless?
      //  Here we assume that these regions are typeless, even though the
      //  symbol is typed.
      SymbolRef Sym = cast<loc::SymbolVal>(&BaseL)->getSymbol();
      // Create a region to represent this symbol.
      // FIXME: In the future we may just use symbolic regions instead of
      //  SymbolVals to reason about symbolic memory chunks.
      const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym);
      // Layered a typed region on top of this.
      QualType T = StateMgr.getSymbolManager().getType(Sym);
      BaseR = MRMgr.getAnonTypedRegion(T, SymR);
      break;
    }
      
    case loc::GotoLabelKind:
    case loc::FuncValKind:
      // Technically we can get here if people do funny things with casts.
{'fraction_non_alphanumeric': 0.12292638177509364, 'fraction_numerical': 0.0006115740386820579, 'mean_word_length': 2.73025377815797, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2331896', 'n_tokens_mistral': 3930, 'n_tokens_neox': 3838, 'n_words': 1104}