ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
assignment(false),
- assignment_target(0)
+ record_target(false),
+ assignment_target(0),
+ indeterminate_target(false),
+ self_referencing(false)
{ }
void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
{
- if(assignment)
- assignment_target = var.declaration;
+ if(record_target)
+ {
+ if(assignment_target)
+ indeterminate_target = true;
+ else
+ assignment_target = var.declaration;
+ }
else
{
unused_nodes.erase(var.declaration);
+
map<VariableDeclaration *, Node *>::iterator i = assignments.find(var.declaration);
if(i!=assignments.end())
{
unused_nodes.erase(i->second);
assignments.erase(i);
}
+
+ if(assignment && var.declaration==assignment_target)
+ self_referencing = true;
}
}
{
if(binary.assignment)
{
- binary.right->visit(*this);
assignment = true;
+ {
+ SetFlag set(record_target);
+ binary.left->visit(*this);
+ }
+ if(binary.oper!="=")
+ self_referencing = true;
+ binary.right->visit(*this);
+ }
+ else if(record_target && binary.oper=="[")
+ {
binary.left->visit(*this);
+ SetForScope<bool> set(record_target, false);
+ binary.right->visit(*this);
}
else
TraversingVisitor::visit(binary);
{
assignment = false;
assignment_target = 0;
+ indeterminate_target = false;
+ self_referencing = false;
TraversingVisitor::visit(expr);
- if(assignment && assignment_target)
+ if(assignment && assignment_target && !indeterminate_target)
{
Node *&assign = assignments[assignment_target];
- if(assign)
+ if(self_referencing)
+ unused_nodes.erase(assign);
+ else if(assign)
unused_nodes.insert(assign);
assign = &expr;
- if(assignment_target->interface!="out" || (stage->type!=FRAGMENT && !assignment_target->linked_declaration))
- unused_nodes.insert(&expr);
- else
+ if(assignment_target->interface=="out" && (stage->type==FRAGMENT || assignment_target->linked_declaration))
unused_nodes.erase(assignment_target);
+ else
+ unused_nodes.insert(&expr);
}
assignment = false;
}
void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
{
unused_nodes.insert(&var);
+ if(var.init_expression)
+ {
+ unused_nodes.insert(&*var.init_expression);
+ assignments[&var] = &*var.init_expression;
+ }
TraversingVisitor::visit(var);
}
if(var.linked_declaration)
var.linked_declaration->linked_declaration = 0;
}
+ else if(var.init_expression && to_remove.count(&*var.init_expression))
+ var.init_expression = 0;
}
void ProgramCompiler::NodeRemover::visit(InterfaceBlock &iface)