+ unused_nodes.insert(&var);
+ if(var.init_expression)
+ record_assignment(var, *var.init_expression, false);
+ }
+ unused_nodes.erase(var.type_declaration);
+ TraversingVisitor::visit(var);
+}
+
+void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
+{
+ SetForScope<Node *> set(aggregate, &iface);
+ unused_nodes.insert(&iface);
+ TraversingVisitor::visit(iface);
+}
+
+void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
+{
+ assignments.push_back(BlockAssignmentMap());
+
+ for(vector<NodePtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+ (*i)->visit(*this);
+ func.body.visit(*this);
+
+ BlockAssignmentMap &block_assignments = assignments.back();
+ for(map<string, VariableDeclaration *>::iterator i=func.body.variables.begin(); i!=func.body.variables.end(); ++i)
+ block_assignments.erase(i->second);
+ for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i)
+ {
+ if(i->first->interface=="out" && stage->type!=FRAGMENT && !i->first->linked_declaration)
+ continue;
+
+ for(vector<Node *>::iterator j=i->second.nodes.begin(); j!=i->second.nodes.end(); ++j)
+ unused_nodes.erase(*j);
+ }
+
+ assignments.pop_back();
+}
+
+void ProgramCompiler::UnusedVariableLocator::merge_down_assignments()
+{
+ BlockAssignmentMap &parent_assignments = assignments[assignments.size()-2];
+ BlockAssignmentMap &block_assignments = assignments.back();
+ for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i)
+ {
+ BlockAssignmentMap::iterator j = parent_assignments.find(i->first);
+ if(j==parent_assignments.end())
+ parent_assignments.insert(*i);
+ else if(i->second.self_referencing || i->second.conditional)