예제 #1
0
int match_endpoints(endp p1, endp p2, endp amatch)
{
  /* Should this be type_equal ? unclear 
     (only real diff, given that we will forbid old style parameter lists,
     is transparent union handling) */
  if (type_compatible(endpoint_type(p1), endpoint_type(p2)))
    {
      if (amatch)
	*amatch = *p2;
      return 1;
    }
  else
    return 0;
}
예제 #2
0
    std::shared_ptr<Instantiation<Impl>>
    Module_scanner<Impl>::create_instantiation(ast::Module_instantiation const& node) {
      std::shared_ptr<Instantiation<Impl>> inst(new Instantiation<Impl>);
      std::string module_name;

      inst->name = dynamic_cast<ast::Identifier const&>(node.instance_name()).identifier();
      if( m_mod.instantiations.count(inst->name) > 0 )
        throw std::runtime_error(std::string("Instantiation with name ")
            + inst->name
            + std::string(" already exists"));

      if( node.is_template_instantiation() ) {
        LOG4CXX_TRACE(Namespace_scanner<Impl>::m_logger, "instantiating module template");
        // extract name
        auto tmpl_id = node.template_identifier();
        std::vector<Label> qname = tmpl_id.name();
        std::string qname_join = boost::algorithm::join(qname, "::");

        // find template
        std::shared_ptr<Module_template<Impl>> tmpl;
        if( qname.size() > 1 ) {
          tmpl = find_by_path(m_mod,
              &Module<Impl>::module_templates,
              qname);
        } else {
          tmpl = find_module_template(m_mod, qname[0]);
        }

        if( !tmpl ) {
          std::stringstream strm;
          strm << "Can not find module template with name '"
            << qname_join
            << "'";
          throw std::runtime_error(strm.str());
        }

        // determine module name and type overrides
        module_name = qname_join + '<';
        auto type_names = tmpl_id.arg_type_names();
        std::map<Label,std::shared_ptr<Type<Impl>>> types;
        auto it_placeholder = tmpl->type_names.begin();
        for(auto it=type_names.begin();
            (it != type_names.end()) && (it_placeholder != tmpl->type_names.end()); ) {
          // find type
          auto ty = find_type(m_mod, *it);
          if( !ty ) {
            std::stringstream strm;
            strm << node.location() << ": "
              << "failed to find type '"
              << *it
              << "' in instantiation of template '"
              << qname_join
              << "'";
            throw std::runtime_error(strm.str());
          }
          types[*it_placeholder] = ty;

          // append name
          module_name += *it;
          if( ++it != type_names.end() )
            module_name += ',';
          ++it_placeholder;
        }
        module_name += '>';

        // run Module_scanner
        inst->module = this->instantiate_module_template(module_name,
            tmpl->module_node,
          types);
    } else {
      if( typeid(node.module_name()) == typeid(ast::Qualified_name) ) {
        auto const& qn = dynamic_cast<ast::Qualified_name const&>(node.module_name()).name();
        if( qn.size() > 1 ) {
          inst->module = find_by_path(m_mod,
              &Module<Impl>::modules,
              qn);
        } else {
          inst->module = find_module(m_mod, qn[0]);
        }
      } else {
        std::stringstream strm;
        strm << node.location()
          << "Expecting a qualified name as module for now ("
          << __func__
          << ")";
        throw std::runtime_error(strm.str());
      }
    }

    if( !inst->module ) {
      std::stringstream strm;
      strm << node.location();
      strm << ": module '" << module_name << "' not found.";
      throw std::runtime_error(strm.str());
    }

    std::set<Label> matched_ports;
    for(auto& i : node.connection_items()) {
      if( typeid(*i) == typeid(ast::Connection_item) ) {
        auto& con_item = dynamic_cast<ast::Connection_item const&>(*i);
        auto port_name = con_item.port_name().identifier();
        //auto signal_name = con_item.signal_name().identifier();

        if( matched_ports.count(port_name) > 0 ) {
          std::stringstream strm;
          strm << con_item.port_name().location();
          strm << ": Port already connected";
          throw std::runtime_error(strm.str());
        }

        std::shared_ptr<Port_assignment<Impl>> port_assign(new Port_assignment<Impl>());
        port_assign->port = find_port(*(inst->module), port_name);
        if( !port_assign->port ) {
          std::stringstream strm;
          strm << con_item.port_name().location();
          strm << ": port '" << port_name << "' not found.";
          throw std::runtime_error(strm.str());
        }

        //port_assign->object = find_object(m_mod, signal_name);
        //if( !port_assign->object ) {
          //std::stringstream strm;
          //strm << con_item.signal_name().location();
          //strm << ": assigned object '" << signal_name << "' not found.";
          //throw std::runtime_error(strm.str());
        //}

        //if( !type_compatible(*(port_assign->port->type), *(port_assign->object->type)) ) {
          //std::stringstream strm;
          //strm << con_item.location();
          //strm << ": incompatible types in port assignment: expected type '"
            //<< *(port_assign->port->type)
            //<< "' got '"
            //<< *(port_assign->object->type) << "'";
          //throw std::runtime_error(strm.str());
        //}

        inst->connection.push_back(port_assign);
        matched_ports.insert(port_name);
      } else if( typeid(*i) == typeid(ast::Identifier) ) {
        auto& obj_name = dynamic_cast<ast::Identifier const&>(*i).identifier();
        auto assignee = find_object(m_mod, obj_name);

        if( !assignee ) {
          std::stringstream strm;
          strm << i->location()
            << ": object '" << obj_name << "' not found";
          throw std::runtime_error(strm.str());
        }

        auto assignee_socket = find_socket(m_mod, assignee->type->name);
        if( !assignee_socket ) {
          std::stringstream strm;
          strm << i->location()
            << ": object '" << obj_name << "' of type '" << assignee->type->name
            << "' is not a socket";
          throw std::runtime_error(strm.str());
        }

        for(auto assignee_port_pair : assignee_socket->elements) {
          auto port_name = assignee_port_pair.first;
          auto assignee_port = assignee_port_pair.second;
          auto searchit = assignee->type->elements.find(port_name);
          if( searchit != assignee->type->elements.end() ) {
            auto it = searchit->second;
            if( !type_compatible(*(it->type), *(assignee_port->type)) ) {
              std::stringstream strm;
              strm << i->location()
                << ": name match for port '" << port_name << "'"
                << " but no type match (expected: "
                << *(it->type)
                << ", got: "
                << *(assignee_port->type)
                << ")";
              throw std::runtime_error(strm.str());
            }

            if( matched_ports.count(assignee_port->name) > 0 ) {
              std::stringstream strm;
              strm << i->location()
                << ": port '" << assignee_port->name << "' already matched";
              throw std::runtime_error(strm.str());
            }

            std::shared_ptr<Port_assignment<Impl>> port_assign(new Port_assignment<Impl>);
            port_assign->port = it;
            // XXX assign object to element of composite type socket
            inst->connection.push_back(port_assign);
            matched_ports.insert(assignee_port->name);
          }
        }
      } else
        throw std::runtime_error("connection items should be either a list or a single identifier");
    }
    m_mod.instantiations[inst->name] = inst;

    auto obj = std::make_shared<Object<Impl>>();
    obj->name = inst->name;
    obj->type = inst->module->socket;

    m_mod.objects[obj->name] = obj;

    return inst;
  }
예제 #3
0
exprt dereferencet::read_object(
  const exprt &object,
  const exprt &offset,
  const typet &type)
{
  const typet &object_type=ns.follow(object.type());
  const typet &dest_type=ns.follow(type);

  // is the object an array with matching subtype?

  exprt simplified_offset=simplify_expr(offset, ns);

  // check if offset is zero
  if(simplified_offset.is_zero())
  {
    // check type
    if(base_type_eq(object_type, dest_type, ns))
    {
      return object; // trivial case
    }
    else if(type_compatible(object_type, dest_type))
    {
      // the type differs, but we can do this with a typecast
      return typecast_exprt(object, dest_type);
    }
  }

  if(object.id()==ID_index)
  {
    const index_exprt &index_expr=to_index_expr(object);

    exprt index=index_expr.index();

    // multiply index by object size
    exprt size=size_of_expr(object_type, ns);

    if(size.is_nil())
      throw "dereference failed to get object size for index";

    index.make_typecast(simplified_offset.type());
    size.make_typecast(index.type());

    exprt new_offset=plus_exprt(simplified_offset, mult_exprt(index, size));

    return read_object(index_expr.array(), new_offset, type);
  }
  else if(object.id()==ID_member)
  {
    const member_exprt &member_expr=to_member_expr(object);

    const typet &compound_type=
      ns.follow(member_expr.struct_op().type());

    if(compound_type.id()==ID_struct)
    {
      const struct_typet &struct_type=
        to_struct_type(compound_type);

      exprt member_offset=member_offset_expr(
        struct_type, member_expr.get_component_name(), ns);

      if(member_offset.is_nil())
        throw "dereference failed to get member offset";

      member_offset.make_typecast(simplified_offset.type());

      exprt new_offset=plus_exprt(simplified_offset, member_offset);

      return read_object(member_expr.struct_op(), new_offset, type);
    }
    else if(compound_type.id()==ID_union)
    {
      // Unions are easy: the offset is always zero,
      // so simply pass down.
      return read_object(member_expr.struct_op(), offset, type);
    }
  }

  // check if we have an array with the right subtype
  if(object_type.id()==ID_array &&
     base_type_eq(object_type.subtype(), dest_type, ns))
  {
    // check proper alignment
    exprt size=size_of_expr(dest_type, ns);

    if(size.is_not_nil())
    {
      mp_integer size_constant, offset_constant;
      if(!to_integer(simplify_expr(size, ns), size_constant) &&
         !to_integer(simplified_offset, offset_constant) &&
         (offset_constant%size_constant)==0)
      {
        // Yes! Can use index expression!
        mp_integer index_constant=offset_constant/size_constant;
        exprt index_expr=from_integer(index_constant, size.type());
        return index_exprt(object, index_expr, dest_type);
      }
    }
  }

  // give up and use byte_extract
  return binary_exprt(object, byte_extract_id(), simplified_offset, dest_type);
}
예제 #4
0
파일: expr.c 프로젝트: CARV-ICS-FORTH/scoop
/* Return TRUE if no error and lhstype and rhstype are not error_type */
bool check_assignment(type lhstype, type rhstype, expression rhs,
		      const char *context, data_declaration fundecl,
		      const char *funname, int parmnum)
{
  bool zerorhs = rhs && definite_zero(rhs);

  if (lhstype == error_type || rhstype == error_type)
    return FALSE;

  if (type_void(rhstype))
    {
      error("void value not ignored as it ought to be");
      return FALSE;
    }

  if (type_equal_unqualified(lhstype, rhstype))
    return TRUE;

  if (type_arithmetic(lhstype) && type_arithmetic(rhstype))
    {
      if (rhs)
	constant_overflow_warning(rhs->cst);
      return check_conversion(lhstype, rhstype);
    }
  if (parmnum && (type_qualifiers(lhstype) & transparent_qualifier))
    {
      /* See if we can match any field of lhstype */
      tag_declaration tag = type_tag(lhstype);
      field_declaration fields, marginal_field = NULL;

      /* I blame gcc for this horrible mess (and it's minor inconsistencies
	 with the regular rules) */
      /* pedantic warnings are skipped in here because we're already
	 issuing a warning for the use of this construct */
      for (fields = tag->fieldlist; fields; fields = fields->next)
	{
	  type ft = fields->type;

	  if (type_compatible(ft, rhstype))
	    break;

	  if (!type_pointer(ft))
	    continue;

	  if (type_pointer(rhstype))
	    {
	      type ttl = type_points_to(ft), ttr = type_points_to(rhstype);
	      bool goodmatch = assignable_pointer_targets(ttl, ttr, FALSE);

	      /* Any non-function converts to a [const][volatile] void *
		 and vice versa; otherwise, targets must be the same.
		 Meanwhile, the lhs target must have all the qualifiers of
		 the rhs.  */
	      if (goodmatch)
		{
		  /* If this type won't generate any warnings, use it.  */
		  if ((type_function(ttr) && type_function(ttl))
		      ? (((!type_const(ttl)) | type_const(ttr))
			 & ((!type_volatile(ttl)) | type_volatile(ttr)))
		      : (((type_const(ttl)) | (!type_const(ttr)))
			 & (type_volatile(ttl) | (!type_volatile(ttr)))))
		    break;

		  /* Keep looking for a better type, but remember this one.  */
		  if (!marginal_field)
		    marginal_field = fields;
		}
	    }

	  /* Can convert integer zero to any pointer type.  */
	  /* Note that this allows passing *any* null pointer (gcc bug?) */
	  if (zerorhs)
	    break;
	}

      if (fields || marginal_field)
	{
	  if (!fields)
	    {
	      /* We have only a marginally acceptable member type;
		 it needs a warning.  */
	      type ttl = type_points_to(marginal_field->type),
		ttr = type_points_to(rhstype);

	      ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum,
				     FALSE);
	    }
	  
	  if (pedantic && !(fundecl && fundecl->in_system_header))
	    pedwarn("ANSI C prohibits argument conversion to union type");

	  return TRUE;
	}
    }

  if (type_pointer(lhstype) && type_pointer(rhstype))
    {
      type ttl = type_points_to(lhstype), ttr = type_points_to(rhstype);
      bool goodmatch = assignable_pointer_targets(ttl, ttr, pedantic);

      /* Any non-function converts to a [const][volatile] void *
	 and vice versa; otherwise, targets must be the same.
	 Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
      if (goodmatch || (type_equal_unqualified(make_unsigned_type(ttl),
					       make_unsigned_type(ttr))))
	ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum,
			       pedantic);
      else
	warn_for_assignment("%s from incompatible pointer type",
			    context, funname, parmnum);

      return check_conversion(lhstype, rhstype);
    }
  /* enum = ptr and ptr = enum counts as an error, so use type_integral */
  else if (type_pointer(lhstype) && type_integral(rhstype))
    {
      if (!zerorhs)
	warn_for_assignment("%s makes pointer from integer without a cast",
			    context, funname, parmnum);
      return check_conversion(lhstype, rhstype);
    }
  else if (type_integral(lhstype) && type_pointer(rhstype))
    {
      warn_for_assignment("%s makes integer from pointer without a cast",
			  context, funname, parmnum);
      return check_conversion(lhstype, rhstype);
    }

  if (!context)
    if (funname)
      error("incompatible type for argument %d of `%s'", parmnum, funname);
    else
      error("incompatible type for argument %d of indirect function call",
	    parmnum);
  else
    error("incompatible types in %s", context);

  return FALSE;
}