예제 #1
0
std::string counterexample_value_binary(
  const exprt &expr,
  const namespacet &ns)
{
  const typet &type=ns.follow(expr.type());
  
  if(expr.id()==ID_constant)
  {
    if(type.id()==ID_unsignedbv ||
       type.id()==ID_signedbv ||
       type.id()==ID_bv ||
       type.id()==ID_fixedbv ||
       type.id()==ID_floatbv ||
       type.id()==ID_pointer)
    {
      return expr.get_string(ID_value);
    }
    else if(type.id()==ID_bool)
    {
      return expr.is_true()?"1":"0";
    }
  }
  else if(expr.id()==ID_array)
  {
    std::string result;
  
    forall_operands(it, expr)
    {
      if(result=="") result="{ "; else result+=", ";
      result+=counterexample_value_binary(*it, ns);
    }
      
    return result+" }";
  }
예제 #2
0
/// checks whether a termination argument implies termination
threevalt summarizer_fw_termt::check_termination_argument(exprt expr)
{
  if(expr.is_false())
    return YES;

  // should be of the form /\_i g_i=> R_i
  if(expr.id()==ID_and)
  {
    threevalt result=YES;
    for(exprt::operandst::iterator it=expr.operands().begin();
        it!=expr.operands().end(); it++)
    {
      if(it->is_true())
        result=UNKNOWN;
      if(it->id()==ID_implies)
      {
        if(it->op1().is_true())
          result=UNKNOWN;
      }
    }
    return result;
  }
  else
  {
    if(expr.id()==ID_implies)
    {
      if(expr.op1().is_true())
        return UNKNOWN;
    }
    else
      return !expr.is_true() ? YES : UNKNOWN;
  }
  return YES;
}
예제 #3
0
파일: guard.cpp 프로젝트: diffblue/cbmc
void guardt::add(const exprt &expr)
{
  assert(expr.type().id()==ID_bool);

  if(is_false() || expr.is_true())
    return;
  else if(is_true() || expr.is_false())
  {
    *this=expr;

    return;
  }
  else if(id()!=ID_and)
  {
    and_exprt a;
    a.copy_to_operands(*this);
    *this=a;
  }

  operandst &op=operands();

  if(expr.id()==ID_and)
    op.insert(op.end(),
              expr.operands().begin(),
              expr.operands().end());
  else
    op.push_back(expr);
}
예제 #4
0
void invariant_sett::strengthen_rec(const exprt &expr)
{
  if(expr.type().id()!=ID_bool)
    throw "non-Boolean argument to strengthen()";

  #if 0
  std::cout << "S: " << from_expr(*ns, "", expr) << '\n';
  #endif

  if(is_false)
  {
    // we can't get any stronger
    return;
  }

  if(expr.is_true())
  {
    // do nothing, it's useless
  }
  else if(expr.is_false())
  {
    // wow, that's strong
    make_false();
  }
  else if(expr.id()==ID_not)
  {
    // give up, we expect NNF
  }
  else if(expr.id()==ID_and)
  {
    forall_operands(it, expr)
      strengthen_rec(*it);
  }
  else if(expr.id()==ID_le ||
          expr.id()==ID_lt)
  {
    assert(expr.operands().size()==2);

    // special rule: x <= (a & b)
    // implies:      x<=a && x<=b

    if(expr.op1().id()==ID_bitand)
    {
      const exprt &bitand_op=expr.op1();

      forall_operands(it, bitand_op)
      {
        exprt tmp(expr);
        tmp.op1()=*it;
        strengthen_rec(tmp);
      }

      return;
    }
예제 #5
0
bool interval_domaint::ai_simplify(
  exprt &condition,
  const namespacet &ns) const
{
  bool unchanged=true;
  interval_domaint d(*this);

  // merge intervals to properly handle conjunction
  if(condition.id()==ID_and)              // May be directly representable
  {
    interval_domaint a;
    a.make_top();                         // a is everything
    a.assume(condition, ns);              // Restrict a to an over-approximation
                                          //  of when condition is true
    if(!a.join(d))                        // If d (this) is included in a...
    {                                     // Then the condition is always true
      unchanged=condition.is_true();
      condition.make_true();
    }
  }
  else if(condition.id()==ID_symbol)
  {
    // TODO: we have to handle symbol expression
  }
  else                                    // Less likely to be representable
  {
    d.assume(not_exprt(condition), ns);   // Restrict to when condition is false
    if(d.is_bottom())                     // If there there are none...
    {                                     // Then the condition is always true
      unchanged=condition.is_true();
      condition.make_true();
    }
  }

  return unchanged;
}
예제 #6
0
void guardt::add(const exprt &expr)
{
  if(expr.id()==ID_and && expr.type().id()==ID_bool)
  {
    forall_operands(it, expr)
      add(*it);

    return;
  }

  if(expr.is_true())
  {
  }
  else
    guard_list.push_back(expr);
}
예제 #7
0
파일: cvc_conv.cpp 프로젝트: diffblue/cbmc
void cvc_convt::convert_as_bv(const exprt &expr)
{
    if(expr.type().id()==ID_bool)
    {
        if(expr.is_true())
            out << "0bin1";
        else if(expr.is_false())
            out << "0bin0";
        else
        {
            out << "IF ";
            convert_expr(expr);
            out << " THEN 0bin1 ELSE 0bin0 ENDIF";
        }
    }
    else
        convert_expr(expr);
}
예제 #8
0
void termination_baset::adjust_assertion(
  const exprt &expr,
  goto_tracet &trace)
{
  status("Adjusting termination assertion.");

  if(trace.steps.empty())
    throw "counterexample is too short";

  goto_trace_stept &assertion=trace.steps.back();

  assert(assertion.is_assert());

  // HACK: nasty cast!
  goto_programt::targett &orig_assertion=
      (*((goto_programt::targett*)(&assertion.pc)));

  exprt &guard=orig_assertion->guard;
  assert(guard.id()=="=>" && guard.operands().size()==2);

  if(expr.is_true()) // to cancel the termination check
  {
    guard.make_true();
  }
  else if(guard.op1().id()=="or")
  {
    guard.op1().copy_to_operands(expr);
  }
  else
  {
    or_exprt new_rel;
    new_rel.move_to_operands(guard.op1());
    new_rel.copy_to_operands(expr);

    guard.op1()=new_rel;
  }

  debug("NEW ASSERTION: " + from_expr(ns, "", guard));
}
예제 #9
0
파일: cvc_conv.cpp 프로젝트: diffblue/cbmc
literalt cvc_convt::convert(const exprt &expr)
{
    //out << "%% E: " << expr << std::endl;

    if(expr.type().id()!=ID_bool)
    {
        std::string msg="cvc_convt::convert got "
                        "non-boolean expression: ";
        msg+=expr.pretty();
        throw msg;
    }

    // Three special cases in which we don't need to generate
    // a handle.

    if(expr.is_true())
        return const_literal(true);
    else if(expr.is_false())
        return const_literal(false);
    else if(expr.id()==ID_literal)
        return to_literal_expr(expr).get_literal();

    // Generate new handle

    literalt l(no_boolean_variables, false);
    no_boolean_variables++;

    find_symbols(expr);

    // define new handle
    out << "ASSERT ";
    convert_literal(l);
    out << " <=> (";
    convert_expr(expr);
    out << ");" << std::endl << std::endl;

    return l;
}
예제 #10
0
파일: xml_expr.cpp 프로젝트: Dthird/CBMC
xmlt xml(
  const exprt &expr,
  const namespacet &ns)
{
  xmlt result;
  
  const typet &type=ns.follow(expr.type());

  if(expr.id()==ID_constant)
  {
    if(type.id()==ID_unsignedbv ||
       type.id()==ID_signedbv ||
       type.id()==ID_c_bit_field)
    {
      std::size_t width=to_bitvector_type(type).get_width();
    
      result.name="integer";
      result.set_attribute("binary", expr.get_string(ID_value));
      result.set_attribute("width", width);
      
      const typet &underlying_type=
        type.id()==ID_c_bit_field?type.subtype():
        type;

      bool is_signed=underlying_type.id()==ID_signedbv;
        
      std::string sig=is_signed?"":"unsigned ";

      if(width==config.ansi_c.char_width)
        result.set_attribute("c_type", sig+"char");
      else if(width==config.ansi_c.int_width)
        result.set_attribute("c_type", sig+"int");
      else if(width==config.ansi_c.short_int_width)
        result.set_attribute("c_type", sig+"short int");
      else if(width==config.ansi_c.long_int_width)
        result.set_attribute("c_type", sig+"long int");
      else if(width==config.ansi_c.long_long_int_width)
        result.set_attribute("c_type", sig+"long long int");

      mp_integer i;
      if(!to_integer(expr, i))
        result.data=integer2string(i);
    }
    else if(type.id()==ID_c_enum)
    {
      result.name="integer";
      result.set_attribute("binary", expr.get_string(ID_value));
      result.set_attribute("width", type.subtype().get_string(ID_width));
      result.set_attribute("c_type", "enum");

      mp_integer i;
      if(!to_integer(expr, i))
        result.data=integer2string(i);
    }
    else if(type.id()==ID_c_enum_tag)
    {
      constant_exprt tmp;
      tmp.type()=ns.follow_tag(to_c_enum_tag_type(type));
      tmp.set_value(to_constant_expr(expr).get_value());
      return xml(tmp, ns);
    }
    else if(type.id()==ID_bv)
    {
      result.name="bitvector";
      result.set_attribute("binary", expr.get_string(ID_value));
    }
    else if(type.id()==ID_fixedbv)
    {
      result.name="fixed";
      result.set_attribute("width", type.get_string(ID_width));
      result.set_attribute("binary", expr.get_string(ID_value));
      result.data=fixedbvt(to_constant_expr(expr)).to_ansi_c_string();
    }
    else if(type.id()==ID_floatbv)
    {
      result.name="float";
      result.set_attribute("width", type.get_string(ID_width));
      result.set_attribute("binary", expr.get_string(ID_value));
      result.data=ieee_floatt(to_constant_expr(expr)).to_ansi_c_string();
    }
    else if(type.id()==ID_pointer)
    {
      result.name="pointer";
      result.set_attribute("binary", expr.get_string(ID_value));
      if(expr.get(ID_value)==ID_NULL)
        result.data="NULL";
    }
    else if(type.id()==ID_bool)
    {
      result.name="boolean";
      result.set_attribute("binary", expr.is_true()?"1":"0");
      result.data=expr.is_true()?"TRUE":"FALSE";
    }
    else
    {
      result.name="unknown";
    }
  }
  else if(expr.id()==ID_array)
  {
    result.name="array";
    
    unsigned index=0;
    
    forall_operands(it, expr)
    {
      xmlt &e=result.new_element("element");
      e.set_attribute("index", index);
      e.new_element(xml(*it, ns));
      index++;
    }
예제 #11
0
xmlt xml(
  const exprt &expr,
  const namespacet &ns)
{
  const typet &type=ns.follow(expr.type());
  xmlt result;
  
  if(expr.id()==ID_constant)
  {
    if(type.id()==ID_unsignedbv ||
       type.id()==ID_signedbv)
    {
      result.name="integer";
      result.set_attribute("binary", expr.get_string(ID_value));

      mp_integer i;
      if(!to_integer(expr, i))
        result.data=integer2string(i);
    }
    else if(type.id()==ID_bv)
    {
      result.name="bitvector";
      result.set_attribute("binary", expr.get_string(ID_value));
      result.data=expr.get_string(ID_value);
    }
    else if(type.id()==ID_fixedbv)
    {
      result.name="fixed";
      result.set_attribute("binary", expr.get_string(ID_value));
      result.data=fixedbvt(to_constant_expr(expr)).to_ansi_c_string();
    }
    else if(type.id()==ID_floatbv)
    {
      result.name="float";
      result.set_attribute("binary", expr.get_string(ID_value));
      result.data=ieee_floatt(to_constant_expr(expr)).to_ansi_c_string();
    }
    else if(type.id()==ID_pointer)
    {
      result.name="pointer";
      result.set_attribute("binary", expr.get_string(ID_value));
      if(expr.get(ID_value)==ID_NULL)
        result.data="NULL";
    }
    else if(type.id()==ID_bool)
    {
      result.name="boolean";
      result.set_attribute("binary", expr.is_true()?"1":"0");
      result.data=expr.is_true()?"TRUE":"FALSE";
    }
    else
    {
      result.name="unknown";
    }
  }
  else if(expr.id()==ID_array)
  {
    result.name="array";
    
    unsigned index=0;
    
    forall_operands(it, expr)
    {
      xmlt &e=result.new_element("element");
      e.set_attribute("index", index);
      e.new_element(xml(*it, ns));
      index++;
    }
예제 #12
0
void dplib_convt::convert_dplib_expr(const exprt &expr)
{
    if(expr.id()==ID_symbol)
    {
        convert_identifier(expr.get_string(ID_identifier));
    }
    else if(expr.id()==ID_nondet_symbol)
    {
        convert_identifier("nondet$"+expr.get_string(ID_identifier));
    }
    else if(expr.id()==ID_typecast)
    {
        assert(expr.operands().size()==1);
        const exprt &op=expr.op0();

        if(expr.type().id()==ID_bool)
        {
            if(op.type().id()==ID_signedbv ||
                    op.type().id()==ID_unsignedbv ||
                    op.type().id()==ID_pointer)
            {
                convert_dplib_expr(op);
                dplib_prop.out << "/=";
                convert_dplib_expr(gen_zero(op.type()));
            }
            else
            {
                throw "TODO typecast1 "+op.type().id_string()+" -> bool";
            }
        }
        else if(expr.type().id()==ID_signedbv ||
                expr.type().id()==ID_unsignedbv)
        {
            unsigned to_width=unsafe_string2unsigned(id2string(expr.type().get(ID_width)));

            if(op.type().id()==ID_signedbv)
            {
                unsigned from_width=unsafe_string2unsigned(id2string(op.type().get(ID_width)));

                if(from_width==to_width)
                    convert_dplib_expr(op);
                else if(from_width<to_width)
                {
                    dplib_prop.out << "SX(";
                    convert_dplib_expr(op);
                    dplib_prop.out << ", " << to_width << ")";
                }
                else
                {
                    dplib_prop.out << "(";
                    convert_dplib_expr(op);
                    dplib_prop.out << ")[" << (to_width-1) << ":0]";
                }
            }
            else if(op.type().id()==ID_unsignedbv)
            {
                unsigned from_width=unsafe_string2unsigned(id2string(op.type().get(ID_width)));

                if(from_width==to_width)
                    convert_dplib_expr(op);
                else if(from_width<to_width)
                {
                    dplib_prop.out << "(0bin";

                    for(unsigned i=from_width; i<to_width; i++)
                        dplib_prop.out << "0";

                    dplib_prop.out << " @ ";

                    dplib_prop.out << "(";
                    convert_dplib_expr(op);
                    dplib_prop.out << "))";
                }
                else
                {
                    dplib_prop.out << "(";
                    convert_dplib_expr(op);
                    dplib_prop.out << ")[" << (to_width-1) << ":0]";
                }
            }
            else if(op.type().id()==ID_bool)
            {
                if(to_width>1)
                {
                    dplib_prop.out << "(0bin";

                    for(unsigned i=1; i<to_width; i++)
                        dplib_prop.out << "0";

                    dplib_prop.out << " @ ";

                    dplib_prop.out << "IF ";
                    convert_dplib_expr(op);
                    dplib_prop.out << " THEN 0bin1 ELSE 0bin0 ENDIF)";
                }
                else
                {
                    dplib_prop.out << "IF ";
                    convert_dplib_expr(op);
                    dplib_prop.out << " THEN 0bin1 ELSE 0bin0 ENDIF";
                }
            }
            else
            {
                throw "TODO typecast2 "+op.type().id_string()+
                " -> "+expr.type().id_string();
            }
        }
        else if(expr.type().id()==ID_pointer)
        {
            if(op.type().id()==ID_pointer)
            {
                convert_dplib_expr(op);
            }
            else
                throw "TODO typecast3 "+op.type().id_string()+" -> pointer";
        }
        else
            throw "TODO typecast4 ? -> "+expr.type().id_string();
    }
    else if(expr.id()==ID_struct)
    {
        dplib_prop.out << "(# ";

        const struct_typet &struct_type=to_struct_type(expr.type());

        const struct_typet::componentst &components=
            struct_type.components();

        assert(components.size()==expr.operands().size());

        unsigned i=0;
        for(struct_typet::componentst::const_iterator
                it=components.begin();
                it!=components.end();
                it++, i++)
        {
            if(i!=0) dplib_prop.out << ", ";
            dplib_prop.out << it->get(ID_name);
            dplib_prop.out << ":=";
            convert_dplib_expr(expr.operands()[i]);
        }

        dplib_prop.out << " #)";
    }
    else if(expr.id()==ID_constant)
    {
        if(expr.type().id()==ID_unsignedbv ||
                expr.type().id()==ID_signedbv ||
                expr.type().id()==ID_bv)
        {
            dplib_prop.out << "0bin" << expr.get(ID_value);
        }
        else if(expr.type().id()==ID_pointer)
        {
            const irep_idt &value=expr.get(ID_value);

            if(value=="NULL")
            {
                dplib_prop.out << "(# object:="
                               << pointer_logic.get_null_object()
                               << ", offset:="
                               << bin_zero(config.ansi_c.pointer_width) << " #)";
            }
            else
                throw "unknown pointer constant: "+id2string(value);
        }
        else if(expr.type().id()==ID_bool)
        {
            if(expr.is_true())
                dplib_prop.out << "TRUE";
            else if(expr.is_false())
                dplib_prop.out << "FALSE";
            else
                throw "unknown boolean constant";
        }
        else if(expr.type().id()==ID_array)
        {
            dplib_prop.out << "ARRAY (i: " << array_index_type() << "):";

            assert(!expr.operands().empty());

            unsigned i=0;
            forall_operands(it, expr)
            {
                if(i==0)
                    dplib_prop.out << "\n  IF ";
                else
                    dplib_prop.out << "\n  ELSIF ";

                dplib_prop.out << "i=" << array_index(i) << " THEN ";
                convert_array_value(*it);
                i++;
            }

            dplib_prop.out << "\n  ELSE ";
            convert_dplib_expr(expr.op0());
            dplib_prop.out << "\n  ENDIF";
        }
        else if(expr.type().id()==ID_integer ||
예제 #13
0
bool prop_convt::get_bool(const exprt &expr, tvt &value) const
{
  // trivial cases

  if(expr.is_true())
  {
    value=tvt(true);
    return false;
  }
  else if(expr.is_false())
  {
    value=tvt(false);
    return false;
  }
  else if(expr.id()==ID_symbol)
  {
    symbolst::const_iterator result=
      symbols.find(to_symbol_expr(expr).get_identifier());
      
    if(result==symbols.end()) return true;

    value=prop.l_get(result->second);
    return false;
  }

  // sub-expressions

  if(expr.id()==ID_not)
  {
    if(expr.type().id()==ID_bool &&
       expr.operands().size()==1)
    {
      if(get_bool(expr.op0(), value)) return true;
      value=!value;
      return false;
    }
  }
  else if(expr.id()==ID_and || expr.id()==ID_or)
  {
    if(expr.type().id()==ID_bool &&
       expr.operands().size()>=1)
    {
      value=tvt(expr.id()==ID_and);

      forall_operands(it, expr)
      {
        tvt tmp;
        if(get_bool(*it, tmp)) return true;

        if(expr.id()==ID_and)
        {
          if(tmp.is_false()) { value=tvt(false); return false; }

          value=value && tmp;
        }
        else // or
        {
          if(tmp.is_true()) { value=tvt(true); return false; }

          value=value || tmp;
        }
      }

      return false;
    }
예제 #14
0
void goto_inlinet::replace_return(
  goto_programt &dest,
  const exprt &lhs,
  const exprt &constrain)
{
  for(goto_programt::instructionst::iterator
      it=dest.instructions.begin();
      it!=dest.instructions.end();
      it++)
  {
    if(it->is_return())
    {
      #if 0
      if(lhs.is_not_nil())
      {
        if(it->code.operands().size()!=1)
        {
          error().source_location=it->code.find_source_location();
          str << "return expects one operand!";
          warning_msg();
          continue;
        }
      
        goto_programt tmp;
        goto_programt::targett assignment=tmp.add_instruction(ASSIGN);
        
        code_assignt code_assign(lhs, it->code.op0());

        // this may happen if the declared return type at the call site
        // differs from the defined return type
        if(code_assign.lhs().type()!=
           code_assign.rhs().type())
          code_assign.rhs().make_typecast(code_assign.lhs().type());

        assignment->code=code_assign;
        assignment->source_location=it->source_location;
        assignment->function=it->function;
        
        if(constrain.is_not_nil() && !constrain.is_true())
        {
          codet constrain(ID_bp_constrain);
          constrain.reserve_operands(2);
          constrain.move_to_operands(assignment->code);
          constrain.copy_to_operands(constrain);
        }
        
        dest.insert_before_swap(it, *assignment);
        it++;
      }
      else if(!it->code.operands().empty())
      {
        goto_programt tmp;
        goto_programt::targett expression=tmp.add_instruction(OTHER);
        
        expression->code=codet(ID_expression);
        expression->code.move_to_operands(it->code.op0());
        expression->source_location=it->source_location;
        expression->function=it->function;
        
        dest.insert_before_swap(it, *expression);
        it++;
      }

      it->make_goto(--dest.instructions.end());
      #else
      if(lhs.is_not_nil())
      {
        if(it->code.operands().size()!=1)
        {
          warning().source_location=it->code.find_source_location();
          warning() << "return expects one operand!\n"
                    << it->code.pretty() << eom;
          continue;
        }
      
        code_assignt code_assign(lhs, it->code.op0());

        // this may happen if the declared return type at the call site
        // differs from the defined return type
        if(code_assign.lhs().type()!=
           code_assign.rhs().type())
          code_assign.rhs().make_typecast(code_assign.lhs().type());

        if(constrain.is_not_nil() && !constrain.is_true())
        {
          codet constrain(ID_bp_constrain);
          constrain.reserve_operands(2);
          constrain.move_to_operands(code_assign);
          constrain.copy_to_operands(constrain);
          it->code=constrain;
          it->type=OTHER;
        }
        else
        {
          it->code=code_assign;
          it->type=ASSIGN;
        }

        it++;
      }
      else if(!it->code.operands().empty())
      {
        codet expression(ID_expression);
        expression.move_to_operands(it->code.op0());
        it->code=expression;
        it->type=OTHER;
        it++;
      }
      #endif
    }
  }
}
예제 #15
0
void interpretert::evaluate(
  const exprt &expr,
  std::vector<mp_integer> &dest) const
{
  if(expr.id()==ID_constant)
  {
    if(expr.type().id()==ID_struct)
    {
    }
    else if(expr.type().id()==ID_floatbv)
    {
      ieee_floatt f;
      f.from_expr(to_constant_expr(expr));
      dest.push_back(f.pack());
      return;
    }
    else if(expr.type().id()==ID_fixedbv)
    {
      fixedbvt f;
      f.from_expr(to_constant_expr(expr));
      dest.push_back(f.get_value());
      return;
    }
    else if(expr.type().id()==ID_bool)
    {
      dest.push_back(expr.is_true());
      return;
    }
    else
    {
      mp_integer i;
      if(!to_integer(expr, i))
      {
        dest.push_back(i);
        return;
      }
    }
  }
  else if(expr.id()==ID_struct)
  {
    dest.reserve(get_size(expr.type()));
    bool error=false;

    forall_operands(it, expr)
    {
      if(it->type().id()==ID_code)
        continue;

      unsigned sub_size=get_size(it->type());
      if(sub_size==0)
        continue;

      std::vector<mp_integer> tmp;
      evaluate(*it, tmp);

      if(tmp.size()==sub_size)
      {
        for(unsigned i=0; i<sub_size; i++)
          dest.push_back(tmp[i]);
      }
      else
        error=true;
    }

    if(!error)
      return;

    dest.clear();
  }
예제 #16
0
json_objectt json(
  const exprt &expr,
  const namespacet &ns)
{
  json_objectt result;
  
  const typet &type=ns.follow(expr.type());

  if(expr.id()==ID_constant)
  {
    if(type.id()==ID_unsignedbv ||
       type.id()==ID_signedbv ||
       type.id()==ID_c_bit_field)
    {
      std::size_t width=to_bitvector_type(type).get_width();
    
      result["name"]=json_stringt("integer");
      result["binary"]=json_stringt(expr.get_string(ID_value));
      result["width"]=json_numbert(i2string(width));
      
      const typet &underlying_type=
        type.id()==ID_c_bit_field?type.subtype():
        type;

      bool is_signed=underlying_type.id()==ID_signedbv;
        
      std::string sig=is_signed?"":"unsigned ";

      if(width==config.ansi_c.char_width)
        result["c_type"]=json_stringt(sig+"char");
      else if(width==config.ansi_c.int_width)
        result["c_type"]=json_stringt(sig+"int");
      else if(width==config.ansi_c.short_int_width)
        result["c_type"]=json_stringt(sig+"short int");
      else if(width==config.ansi_c.long_int_width)
        result["c_type"]=json_stringt(sig+"long int");
      else if(width==config.ansi_c.long_long_int_width)
        result["c_type"]=json_stringt(sig+"long long int");

      mp_integer i;
      if(!to_integer(expr, i))
        result["data"]=json_stringt(integer2string(i));
    }
    else if(type.id()==ID_c_enum)
    {
      result["name"]=json_stringt("integer");
      result["binary"]=json_stringt(expr.get_string(ID_value));
      result["width"]=json_numbert(type.subtype().get_string(ID_width));
      result["c_type"]=json_stringt("enum");

      mp_integer i;
      if(!to_integer(expr, i))
        result["data"]=json_stringt(integer2string(i));
    }
    else if(type.id()==ID_c_enum_tag)
    {
      constant_exprt tmp;
      tmp.type()=ns.follow_tag(to_c_enum_tag_type(type));
      tmp.set_value(to_constant_expr(expr).get_value());
      return json(tmp, ns);
    }
    else if(type.id()==ID_bv)
    {
      result["name"]=json_stringt("bitvector");
      result["binary"]=json_stringt(expr.get_string(ID_value));
    }
    else if(type.id()==ID_fixedbv)
    {
      result["name"]=json_stringt("fixed");
      result["width"]=json_numbert(type.get_string(ID_width));
      result["binary"]=json_stringt(expr.get_string(ID_value));
      result["data"]=
        json_stringt(fixedbvt(to_constant_expr(expr)).to_ansi_c_string());
    }
    else if(type.id()==ID_floatbv)
    {
      result["name"]=json_stringt("float");
      result["width"]=json_numbert(type.get_string(ID_width));
      result["binary"]=json_stringt(expr.get_string(ID_value));
      result["data"]=
        json_stringt(ieee_floatt(to_constant_expr(expr)).to_ansi_c_string());
    }
    else if(type.id()==ID_pointer)
    {
      result["name"]=json_stringt("pointer");
      result["binary"]=json_stringt(expr.get_string(ID_value));
      if(expr.get(ID_value)==ID_NULL)
        result["data"]=json_stringt("NULL");
    }
    else if(type.id()==ID_bool)
    {
      result["name"]=json_stringt("boolean");
      result["binary"]=json_stringt(expr.is_true()?"1":"0");
      result["data"]=jsont::json_boolean(expr.is_true());
    }
    else
    {
      result["name"]=json_stringt("unknown");
    }
  }
  else if(expr.id()==ID_array)
  {
    result["name"]=json_stringt("array");
    json_arrayt &elements=result["elements"].make_array();
    
    unsigned index=0;
    
    forall_operands(it, expr)
    {
      json_objectt &e=elements.push_back().make_object();
      e["index"]=json_numbert(i2string(index));
      e["value"]=json(*it, ns);
      index++;
    }