예제 #1
0
bool java_static_lifetime_init(
  symbol_tablet &symbol_table,
  const source_locationt &source_location,
  message_handlert &message_handler)
{
  symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE);
  code_blockt &code_block=to_code_block(to_code(initialize_symbol.value));
  
  // we need to zero out all static variables
  
  for(symbol_tablet::symbolst::const_iterator
      it=symbol_table.symbols.begin();
      it!=symbol_table.symbols.end();
      it++)
  {
    if(it->second.type.id()!=ID_code &&
       it->second.is_lvalue &&
       it->second.is_state_var &&
       it->second.is_static_lifetime &&
       it->second.value.is_not_nil() &&
       it->second.mode==ID_java)
    {
      code_assignt assignment(it->second.symbol_expr(), it->second.value);
      code_block.add(assignment);
    }
  }
  
  // we now need to run all the <clinit> methods

  for(symbol_tablet::symbolst::const_iterator
      it=symbol_table.symbols.begin();
      it!=symbol_table.symbols.end();
      it++)
  {
    if(it->second.base_name=="<clinit>" &&
       it->second.type.id()==ID_code &&
       it->second.mode==ID_java)
    {
      code_function_callt function_call;
      function_call.lhs()=nil_exprt();
      function_call.function()=it->second.symbol_expr();
      code_block.add(function_call);
    }
  }
  
  return false;
}
예제 #2
0
bool static_lifetime_init(
  symbol_tablet &symbol_table,
  const source_locationt &source_location,
  message_handlert &message_handler)
{
  namespacet ns(symbol_table);

  symbol_tablet::symbolst::iterator s_it=
    symbol_table.symbols.find(INITIALIZE_FUNCTION);

  if(s_it==symbol_table.symbols.end())
    return false;

  symbolt &init_symbol=s_it->second;

  init_symbol.value=code_blockt();
  init_symbol.value.add_source_location()=source_location;

  code_blockt &dest=to_code_block(to_code(init_symbol.value));

  // add the magic label to hide
  dest.add(code_labelt("__CPROVER_HIDE", code_skipt()));

  // do assignments based on "value"

  // sort alphabetically for reproducible results
  std::set<std::string> symbols;

  forall_symbols(it, symbol_table.symbols)
    symbols.insert(id2string(it->first));

  for(const std::string &id : symbols)
  {
    const symbolt &symbol=ns.lookup(id);

    const irep_idt &identifier=symbol.name;

    if(!symbol.is_static_lifetime)
      continue;

    if(symbol.is_type || symbol.is_macro)
      continue;

    // special values
    if(identifier==CPROVER_PREFIX "constant_infinity_uint" ||
       identifier==CPROVER_PREFIX "memory" ||
       identifier=="__func__" ||
       identifier=="__FUNCTION__" ||
       identifier=="__PRETTY_FUNCTION__" ||
       identifier=="argc'" ||
       identifier=="argv'" ||
       identifier=="envp'" ||
       identifier=="envp_size'")
      continue;

    // just for linking
    if(has_prefix(id, CPROVER_PREFIX "architecture_"))
      continue;

    const typet &type=ns.follow(symbol.type);

    // check type
    if(type.id()==ID_code ||
       type.id()==ID_empty)
      continue;

    // We won't try to initialize any symbols that have
    // remained incomplete.

    if(symbol.value.is_nil() &&
       symbol.is_extern)
      // Compilers would usually complain about these
      // symbols being undefined.
      continue;

    if(type.id()==ID_array &&
       to_array_type(type).size().is_nil())
    {
      // C standard 6.9.2, paragraph 5
      // adjust the type to an array of size 1
      symbol_tablet::symbolst::iterator it=
        symbol_table.symbols.find(identifier);
      assert(it!=symbol_table.symbols.end());

      it->second.type=type;
      it->second.type.set(ID_size, from_integer(1, size_type()));
    }

    if(type.id()==ID_incomplete_struct ||
       type.id()==ID_incomplete_union)
      continue; // do not initialize

    if(symbol.value.id()==ID_nondet)
      continue; // do not initialize

    exprt rhs;

    if(symbol.value.is_nil())
    {
      try
      {
        namespacet ns(symbol_table);
        rhs=zero_initializer(symbol.type, symbol.location, ns, message_handler);
        assert(rhs.is_not_nil());
      }
      catch(...)
      {
        return true;
      }
    }
    else
      rhs=symbol.value;

    code_assignt code(symbol.symbol_expr(), rhs);
    code.add_source_location()=symbol.location;

    dest.move_to_operands(code);
  }

  // call designated "initialization" functions

  for(const std::string &id : symbols)
  {
    const symbolt &symbol=ns.lookup(id);

    if(symbol.type.id()==ID_code &&
       to_code_type(symbol.type).return_type().id()==ID_constructor)
    {
      code_function_callt function_call;
      function_call.function()=symbol.symbol_expr();
      function_call.add_source_location()=source_location;
      dest.move_to_operands(function_call);
    }
  }

  return false;
}
예제 #3
0
void c_typecheck_baset::typecheck_for(codet &code)
{
  if(code.operands().size()!=4)
  {
    err_location(code);
    error() << "for expected to have four operands" << eom;
    throw 0;
  }

  // the "for" statement has an implicit block around it,
  // since code.op0() may contain declarations
  //
  // we therefore transform
  //
  //   for(a;b;c) d;
  //
  // to
  //
  //   { a; for(;b;c) d; }
  //
  // if config.ansi_c.for_has_scope

  if(!config.ansi_c.for_has_scope ||
     code.op0().is_nil())
  {
    if(code.op0().is_not_nil())
      typecheck_code(to_code(code.op0()));

    if(code.op1().is_nil())
      code.op1()=true_exprt();
    else
    {
      typecheck_expr(code.op1());
      implicit_typecast_bool(code.op1());
    }

    if(code.op2().is_not_nil())
      typecheck_expr(code.op2());

    if(code.op3().is_not_nil())
    {
      // save & set flags
      bool old_break_is_allowed=break_is_allowed;
      bool old_continue_is_allowed=continue_is_allowed;

      break_is_allowed=continue_is_allowed=true;

      // recursive call
      if(to_code(code.op3()).get_statement()==ID_decl_block)
      {
        code_blockt code_block;
        code_block.add_source_location()=code.op3().source_location();

        code_block.move_to_operands(code.op3());
        code.op3().swap(code_block);
      }
      typecheck_code(to_code(code.op3()));

      // restore flags
      break_is_allowed=old_break_is_allowed;
      continue_is_allowed=old_continue_is_allowed;
    }
  }
  else
  {
    code_blockt code_block;
    code_block.add_source_location()=code.source_location();
    if(to_code(code.op3()).get_statement()==ID_block)
      code_block.set(
        ID_C_end_location,
        to_code_block(to_code(code.op3())).end_location());
    else
      code_block.set(
        ID_C_end_location,
        code.op3().source_location());;

    code_block.reserve_operands(2);
    code_block.move_to_operands(code.op0());
    code.op0().make_nil();
    code_block.move_to_operands(code);
    code.swap(code_block);
    typecheck_code(code); // recursive call
  }

  typecheck_spec_expr(code, ID_C_spec_loop_invariant);
}
예제 #4
0
bool java_static_lifetime_init(
  symbol_tablet &symbol_table,
  const source_locationt &source_location,
  message_handlert &message_handler,
  bool assume_init_pointers_not_null,
  unsigned max_nondet_array_length)
{
  symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE);
  code_blockt &code_block=to_code_block(to_code(initialize_symbol.value));

  // We need to zero out all static variables, or nondet-initialize if they're
  // external. Iterate over a copy of the symtab, as its iterators are
  // invalidated by object_factory:

  std::list<irep_idt> symbol_names;
  for(const auto &entry : symbol_table.symbols)
    symbol_names.push_back(entry.first);

  for(const auto &symname : symbol_names)
  {
    const symbolt &sym=symbol_table.lookup(symname);
    if(should_init_symbol(sym))
    {
      if(sym.value.is_nil() && sym.type!=empty_typet())
      {
        bool allow_null=!assume_init_pointers_not_null;
        if(allow_null)
        {
          std::string namestr=id2string(sym.symbol_expr().get_identifier());
          const std::string suffix="@class_model";
          // Static '.class' fields are always non-null.
          if(has_suffix(namestr, suffix))
            allow_null=false;
          if(allow_null && has_prefix(
               namestr,
               "java::java.lang.String.Literal"))
            allow_null=false;
        }
        auto newsym=object_factory(
          sym.type,
          code_block,
          allow_null,
          symbol_table,
          max_nondet_array_length,
          source_location,
          message_handler);
        code_assignt assignment(sym.symbol_expr(), newsym);
        code_block.add(assignment);
      }
      else if(sym.value.is_not_nil())
      {
        code_assignt assignment(sym.symbol_expr(), sym.value);
        assignment.add_source_location()=source_location;
        code_block.add(assignment);
      }
    }
  }

  // we now need to run all the <clinit> methods

  for(symbol_tablet::symbolst::const_iterator
      it=symbol_table.symbols.begin();
      it!=symbol_table.symbols.end();
      it++)
  {
    if(it->second.base_name=="<clinit>" &&
       it->second.type.id()==ID_code &&
       it->second.mode==ID_java)
    {
      code_function_callt function_call;
      function_call.lhs()=nil_exprt();
      function_call.function()=it->second.symbol_expr();
      function_call.add_source_location()=source_location;
      code_block.add(function_call);
    }
  }

  return false;
}