/*******************************************************************\

Module: Field-insensitive, location-sensitive, over-approximative
        escape analysis

Author: Daniel Kroening, kroening@kroening.com

\*******************************************************************/

#ifndef CPROVER_ESCAPE_ANALYSIS_H
#define CPROVER_ESCAPE_ANALYSIS_H

#include <util/numbering.h>
#include <util/union_find.h>

#include "ai.h"

/*******************************************************************\

   Class: escape_domaint
   
 Purpose:

\*******************************************************************/

class escape_analysist;

class escape_domaint:public ai_domain_baset
{
public:
  escape_domaint():is_bottom(true)
  {
  }
  
  virtual void transform(
    locationt from,
    locationt to,
    ai_baset &ai,
    const namespacet &ns);

  virtual void output(
    std::ostream &out,
    const ai_baset &ai,
    const namespacet &ns) const;

  bool merge(
    const escape_domaint &b,
    locationt from,
    locationt to);
    
  void make_bottom()
  {
    cleanup_map.clear();
    is_bottom=true;
  }
  
  void make_top()
  {
    cleanup_map.clear();
    is_bottom=false;
  }
  
  typedef union_find<irep_idt> aliasest;
  aliasest aliases;
  
  struct cleanupt
  {
    std::set<irep_idt> cleanup_functions;
  };
  
  typedef std::map<irep_idt, cleanupt > cleanup_mapt;
  cleanup_mapt cleanup_map;
  
  bool is_bottom;

protected:  
  void assign_lhs_cleanup(const exprt &, const std::set<irep_idt> &);
  void get_rhs_cleanup(const exprt &, std::set<irep_idt> &);
  void assign_lhs_aliases(const exprt &, const std::set<irep_idt> &);
  void get_rhs_aliases(const exprt &, std::set<irep_idt> &);
  void get_rhs_aliases_address_of(const exprt &, std::set<irep_idt> &);
  irep_idt get_function(const exprt &);
  void check_lhs(const exprt &, std::set<irep_idt> &);
  
  friend class escape_analysist;
  
  bool is_tracked(const symbol_exprt &);
};

class escape_analysist:public ait<escape_domaint> 
{
public:
  void instrument(
    goto_functionst &,
    const namespacet &);

protected:
  virtual void initialize(const goto_functionst &_goto_functions)
  {
  }

  friend class escape_domaint;

  numbering<irep_idt> bits;
  
  void insert_cleanup(
    goto_functionst::goto_functiont &,
    goto_programt::targett,
    const exprt &,
    const std::set<irep_idt> &,
    bool is_object,
    const namespacet &);
};

#endif
