bool has_component_rec(
  const typet &type,
  const irep_idt &component_name,
  const namespacet &ns)
{
  const struct_union_typet &struct_union_type=
    to_struct_union_type(ns.follow(type));

  const struct_union_typet::componentst &components=
    struct_union_type.components();

  for(struct_union_typet::componentst::const_iterator
      it=components.begin();
      it!=components.end();
      it++)
  {
    if(it->get_name()==component_name)
    {
      return true;
    }
    else if(it->get_anonymous())
    {
      if(has_component_rec(it->type(), component_name, ns))
        return true;
    }
  }
  
  return false;
}
Exemplo n.º 2
0
designatort c_typecheck_baset::make_designator(
  const typet &src_type,
  const exprt &src)
{
  assert(!src.operands().empty());

  typet type=src_type;
  designatort designator;

  forall_operands(it, src)
  {
    const exprt &d_op=*it;
    designatort::entryt entry;
    entry.type=type;
    const typet &full_type=follow(entry.type);

    if(full_type.id()==ID_array)
    {
      if(d_op.id()!=ID_index)
      {
        err_location(d_op);
        error() << "expected array index designator" << eom;
        throw 0;
      }

      assert(d_op.operands().size()==1);
      exprt tmp_index=d_op.op0();
      make_constant_index(tmp_index);

      mp_integer index, size;

      if(to_integer(tmp_index, index))
      {
        err_location(d_op.op0());
        error() << "expected constant array index designator" << eom;
        throw 0;
      }

      if(to_array_type(full_type).size().is_nil())
        size=0;
      else if(to_integer(to_array_type(full_type).size(), size))
      {
        err_location(d_op.op0());
        error() << "expected constant array size" << eom;
        throw 0;
      }

      entry.index=integer2size_t(index);
      entry.size=integer2size_t(size);
      entry.subtype=full_type.subtype();
    }
    else if(full_type.id()==ID_struct ||
            full_type.id()==ID_union)
    {
      const struct_union_typet &struct_union_type=
        to_struct_union_type(full_type);

      if(d_op.id()!=ID_member)
      {
        err_location(d_op);
        error() << "expected member designator" << eom;
        throw 0;
      }

      const irep_idt &component_name=d_op.get(ID_component_name);

      if(struct_union_type.has_component(component_name))
      {
        // a direct member
        entry.index=struct_union_type.component_number(component_name);
        entry.size=struct_union_type.components().size();
        entry.subtype=struct_union_type.components()[entry.index].type();
      }
      else
      {
        // We will search for anonymous members,
        // in a loop. This isn't supported by gcc, but icc does allow it.

        bool found=false, repeat;
        typet tmp_type=entry.type;

        do
        {
          repeat=false;
          unsigned number=0;
          const struct_union_typet::componentst &components=
            to_struct_union_type(follow(tmp_type)).components();

          for(struct_union_typet::componentst::const_iterator
              c_it=components.begin();
              c_it!=components.end();
              c_it++, number++)
          {
            if(c_it->get_name()==component_name)
            {
              // done!
              entry.index=number;
              entry.size=components.size();
              entry.subtype=components[entry.index].type();
              entry.type=tmp_type;
            }
            else if(c_it->get_anonymous() &&
                    (follow(c_it->type()).id()==ID_struct ||
                     follow(c_it->type()).id()==ID_union) &&
                    has_component_rec(
                      c_it->type(), component_name, *this))
            {
              entry.index=number;
              entry.size=components.size();
              entry.subtype=c_it->type();
              entry.type=tmp_type;
              tmp_type=entry.subtype;
              designator.push_entry(entry);
              found=repeat=true;
              break;
            }
          }
        }
        while(repeat);

        if(!found)
        {
          err_location(d_op);
          error() << "failed to find struct component `"
                  << component_name << "' in initialization of `"
                  << to_string(struct_union_type) << "'" << eom;
          throw 0;
        }
      }
    }
    else
    {
      err_location(d_op);
      error() << "designated initializers cannot initialize `"
              << to_string(full_type) << "'" << eom;
      throw 0;
    }

    type=entry.subtype;
    designator.push_entry(entry);
  }

  assert(!designator.empty());

  return designator;
}