Beispiel #1
0
void jsil_typecheckt::typecheck_expr_index(exprt &expr)
{
  if(expr.operands().size()!=2)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects two operands" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), jsil_object_type(), true);
  make_type_compatible(expr.op1(), string_typet(), true);

  // special case for function identifiers
  if (expr.op1().id()=="fid" || expr.op1().id()=="constructid")
    expr.type()=code_typet();
  else
    expr.type()=jsil_value_type();
}
Beispiel #2
0
void cpp_typecheckt::static_initialization()
{
  code_blockt block_sini; // Static Initialization Block
  code_blockt block_dini; // Dynamic Initialization Block

  disable_access_control = true;

  // first do zero initialization
  context.foreach_operand([this, &block_sini](const symbolt &s) {
    if(!s.static_lifetime || s.mode != current_mode)
      return;

    // it has a non-code initializer already?
    if(s.value.is_not_nil() && s.value.id() != "code")
      return;

    // it's a declaration only
    if(s.is_extern)
      return;

    if(!s.lvalue)
      return;

    zero_initializer(
      cpp_symbol_expr(s), s.type, s.location, block_sini.operands());
  });

  while(!dinis.empty())
  {
    symbolt &symbol = *context.find_symbol(dinis.front());
    dinis.pop_front();

    if(symbol.is_extern)
      continue;

    if(symbol.mode != current_mode)
      continue;

    assert(symbol.static_lifetime);
    assert(!symbol.is_type);
    assert(symbol.type.id() != "code");

    exprt symexpr = cpp_symbol_expr(symbol);

    if(symbol.value.is_not_nil())
    {
      if(!cpp_is_pod(symbol.type))
      {
        block_dini.move_to_operands(symbol.value);
      }
      else
      {
        exprt symbexpr("symbol", symbol.type);
        symbexpr.identifier(symbol.name);

        codet code;
        code.set_statement("assign");
        code.copy_to_operands(symbexpr, symbol.value);
        code.location() = symbol.location;

        if(symbol.value.id() == "constant")
          block_sini.move_to_operands(code);
        else
          block_dini.move_to_operands(code);
      }

      // Make it nil because we do not want
      // global_init to try to initialize the
      // object
      symbol.value.make_nil();
    }
    else
    {
      exprt::operandst ops;

      codet call = cpp_constructor(locationt(), symexpr, ops);

      if(call.is_not_nil())
        block_dini.move_to_operands(call);
    }
  }

  block_sini.move_to_operands(block_dini);

  // Create the initialization procedure
  symbolt init_symbol;

  init_symbol.name = "#ini#" + id2string(module);
  init_symbol.base_name = "#ini#" + id2string(module);
  init_symbol.value.swap(block_sini);
  init_symbol.mode = current_mode;
  init_symbol.module = module;
  init_symbol.type = code_typet();
  init_symbol.type.add("return_type") = typet("empty");
  init_symbol.type.set("initialization", true);
  init_symbol.is_type = false;
  init_symbol.is_macro = false;

  context.move(init_symbol);

  disable_access_control = false;
}
Beispiel #3
0
void jsil_typecheckt::typecheck_function_call(
  code_function_callt &call)
{
  if(call.operands().size()!=3)
    throw "function call expected to have three operands";

  exprt &lhs=call.lhs();
  typecheck_expr(lhs);

  exprt &f=call.function();
  typecheck_expr(f);

  for(auto &arg : call.arguments())
    typecheck_expr(arg);

  // Look for a function declaration symbol in the symbol table
  if(f.id()==ID_symbol)
  {
    const irep_idt &id=to_symbol_expr(f).get_identifier();

    if(symbol_table.has_symbol(id))
    {
      symbolt &s=symbol_table.lookup(id);

      if(s.type.id()==ID_code)
      {
        code_typet &codet=to_code_type(s.type);

        for(std::size_t i=0; i<codet.parameters().size(); i++)
        {
          if(i>=call.arguments().size()) break;

          const typet &param_type=codet.parameters()[i].type();

          if(!param_type.id().empty() && param_type.is_not_nil())
          {
             // check argument's type if parameter's type is given
             make_type_compatible(call.arguments()[i], param_type, true);
          }
        }

        // if there are too few arguments, add undefined
        if(codet.parameters().size()>call.arguments().size())
        {
          for(std::size_t i=call.arguments().size();
              i<codet.parameters().size();
              ++i)
            call.arguments().push_back(
              exprt("undefined", jsil_undefined_type()));
        }

        // if there are too many arguments, remove
        while(codet.parameters().size()<call.arguments().size())
          call.arguments().pop_back();

        // check return type if exists
        if(!codet.return_type().id().empty() &&
            codet.return_type().is_not_nil())
          make_type_compatible(lhs, codet.return_type(), true);
        else make_type_compatible(lhs, jsil_any_type(), true);
      }
      else
      {
        // TODO: a symbol can be a variable evaluating to a string
        // which corresponds to a function identifier
        make_type_compatible(lhs, jsil_any_type(), true);
      }
    }
    else
    {
      // Should be function, declaration not found yet
      symbolt new_symbol;
      new_symbol.name=id;
      new_symbol.type=code_typet();
      new_symbol.mode="jsil";
      new_symbol.is_type=false;
      new_symbol.value=exprt("no-body-just-yet");

      make_type_compatible(lhs, jsil_any_type(), true);

      if(symbol_table.add(new_symbol))
        throw "failed to add expression symbol to symbol table";
    }
  }
  else
  {
    // TODO: this might be a string literal
    // which corresponds to a function identifier
    make_type_compatible(lhs, jsil_any_type(), true);
  }
}
Beispiel #4
0
void c_typecheck_baset::typecheck_code(codet &code)
{
  if(code.id()!=ID_code)
  {
    err_location(code);
    error() << "expected code, got " << code.pretty() << eom;
    throw 0;
  }

  code.type()=code_typet();

  const irep_idt &statement=code.get_statement();

  if(statement==ID_expression)
    typecheck_expression(code);
  else if(statement==ID_label)
    typecheck_label(to_code_label(code));
  else if(statement==ID_switch_case)
    typecheck_switch_case(to_code_switch_case(code));
  else if(statement==ID_gcc_switch_case_range)
    typecheck_gcc_switch_case_range(code);
  else if(statement==ID_block)
    typecheck_block(code);
  else if(statement==ID_decl_block)
  {
  }
  else if(statement==ID_ifthenelse)
    typecheck_ifthenelse(to_code_ifthenelse(code));
  else if(statement==ID_while)
    typecheck_while(to_code_while(code));
  else if(statement==ID_dowhile)
    typecheck_dowhile(to_code_dowhile(code));
  else if(statement==ID_for)
    typecheck_for(code);
  else if(statement==ID_switch)
    typecheck_switch(to_code_switch(code));
  else if(statement==ID_break)
    typecheck_break(code);
  else if(statement==ID_goto)
    typecheck_goto(to_code_goto(code));
  else if(statement==ID_gcc_computed_goto)
    typecheck_gcc_computed_goto(code);
  else if(statement==ID_continue)
    typecheck_continue(code);
  else if(statement==ID_return)
    typecheck_return(code);
  else if(statement==ID_decl)
    typecheck_decl(code);
  else if(statement==ID_assign)
    typecheck_assign(code);
  else if(statement==ID_skip)
  {
  }
  else if(statement==ID_asm)
    typecheck_asm(code);
  else if(statement==ID_start_thread)
    typecheck_start_thread(code);
  else if(statement==ID_gcc_local_label)
    typecheck_gcc_local_label(code);
  else if(statement==ID_msc_try_finally)
  {
    assert(code.operands().size()==2);
    typecheck_code(to_code(code.op0()));
    typecheck_code(to_code(code.op1()));
  }
  else if(statement==ID_msc_try_except)
  {
    assert(code.operands().size()==3);
    typecheck_code(to_code(code.op0()));
    typecheck_expr(code.op1());
    typecheck_code(to_code(code.op2()));
  }
  else if(statement==ID_msc_leave)
  {
    // fine as is, but should check that we
    // are in a 'try' block
  }
  else if(statement==ID_static_assert)
  {
    assert(code.operands().size()==2);
    typecheck_expr(code.op0());
    typecheck_expr(code.op1());
  }
  else if(statement==ID_CPROVER_try_catch ||
          statement==ID_CPROVER_try_finally)
  {
    assert(code.operands().size()==2);
    typecheck_code(to_code(code.op0()));
    typecheck_code(to_code(code.op1()));
  }
  else if(statement==ID_CPROVER_throw)
  {
    assert(code.operands().empty());
  }
  else if(statement==ID_assume ||
          statement==ID_assert)
  {
    // These are not generated by the C/C++ parsers,
    // but we allow them for the benefit of other users
    // of the typechecker.
    assert(code.operands().size()==1);
    typecheck_expr(code.op0());
  }
  else
  {
    err_location(code);
    error() << "unexpected statement: " << statement << eom;
    throw 0;
  }
}