for(const AggregateMember &m: kvp.second.members)
{
+ string name;
+ if(m.declaration)
+ name = format("%s_%s", kvp.second.declaration->name, m.declaration->name);
+ else
+ name = format("%s_%d", kvp.second.declaration->name, m.index);
+
VariableDeclaration *var = new VariableDeclaration;
var->source = kvp.first->source;
var->line = kvp.first->line;
- var->name = get_unused_variable_name(*kvp.second.decl_scope, format("%s_%s", kvp.second.declaration->name, m.declaration->name));
- var->type = m.declaration->type;
+ var->name = get_unused_variable_name(*kvp.second.decl_scope, name);
+ /* XXX This is kind of brittle and depends on the array declaration's
+ textual type not having brackets in it. */
+ var->type = (m.declaration ? m.declaration : kvp.second.declaration)->type;
if(m.initializer)
var->init_expression = m.initializer->clone();
{
r_aggregate_ref = 0;
expr->visit(*this);
- if(r_aggregate_ref && r_reference.chain_len==1 && (r_reference.chain[0]&0x3F)!=0x3F)
+ if(r_aggregate_ref && r_reference.chain_len==1)
{
- r_aggregate_ref->members[r_reference.chain[0]&0x3F].references.push_back(&expr);
- r_aggregate_ref->members_referenced = true;
+ if((r_reference.chain[0]&0x3F)!=0x3F)
+ {
+ r_aggregate_ref->members[r_reference.chain[0]&0x3F].references.push_back(&expr);
+ r_aggregate_ref->members_referenced = true;
+ }
+ else
+ /* If the accessed member is not known, mark the entire aggregate as
+ referenced. */
+ r_aggregate_ref->referenced = true;
}
r_aggregate_ref = 0;
}
r_reference.declaration = var.declaration;
else
{
+ /* If an aggregate variable is referenced as a whole, it should not be
+ dismantled. */
auto i = aggregates.find(var.declaration);
if(i!=aggregates.end())
i->second.referenced = true;
visit(binary.right);
}
- add_to_chain(r_reference, Assignment::Target::ARRAY, 0x3F);
+ unsigned index = 0x3F;
+ if(Literal *literal_subscript = dynamic_cast<Literal *>(binary.right.get()))
+ if(literal_subscript->value.check_type<int>())
+ index = literal_subscript->value.value<int>();
+ add_to_chain(r_reference, Assignment::Target::ARRAY, index);
+
+ if(r_reference.declaration && r_reference.chain_len==1)
+ {
+ auto i = aggregates.find(r_reference.declaration);
+ r_aggregate_ref = (i!=aggregates.end() ? &i->second : 0);
+ }
+ else
+ r_aggregate_ref = 0;
}
else
{
TraversingVisitor::visit(var);
if(var.interface.empty())
+ {
if(const StructDeclaration *strct = dynamic_cast<const StructDeclaration *>(var.type_declaration))
{
const FunctionCall *init_call = dynamic_cast<const FunctionCall *>(var.init_expression.get());
{
AggregateMember member;
member.declaration = mem_decl;
+ member.index = i;
if(init_call)
member.initializer = init_call->arguments[i];
aggre.members.push_back(member);
}
}
}
+ else if(const Literal *literal_size = dynamic_cast<const Literal *>(var.array_size.get()))
+ {
+ if(literal_size->value.check_type<int>())
+ {
+ Aggregate &aggre = aggregates[&var];
+ aggre.declaration = &var;
+ aggre.decl_scope = current_block;
+ aggre.insert_point = insert_point;
+
+ int size = literal_size->value.value<int>();
+ for(int i=0; i<size; ++i)
+ {
+ AggregateMember member;
+ member.index = i;
+ // Array initializers are not supported yet
+ aggre.members.push_back(member);
+ }
+ }
+ }
+ }
}