docs: def _determine_uses(self, included_files, forward_declarations):
          """Set up the use type of each symbol."""
          file_uses = dict.fromkeys(included_files, UNUSED)
          decl_uses = dict.fromkeys(forward_declarations, UNUSED)
          symbol_table = self.symbol_table
  
          for name, node in forward_declarations.items():
              try:
                  symbol_table.lookup_symbol(node.name, node.namespace)
                  decl_uses[name] |= USES_REFERENCE
              except symbols.Error:
                  module = Module(name, None)
                  symbol_table.add_symbol(node.name, node.namespace, node,
                                          module)
  
          def _do_lookup(name, namespace):
              try:
                  file_use_node = symbol_table.lookup_symbol(name, namespace)
              except symbols.Error:
                  return
              name = file_use_node[1].filename
              file_uses[name] = file_uses.get(name, 0) | USES_DECLARATION
  
          def _add_declaration(name, namespace):
              if not name:
                  # Ignore anonymous struct. It is not standard, but we might as
                  # well avoid crashing if it is easy.
                  return
  
              names = [n for n in namespace if n is not None]
              if names:
                  name = '::'.join(names) + '::' + name
              if name in decl_uses:
                  decl_uses[name] |= USES_DECLARATION
  
          def _add_reference(name, namespace):
              try:
                  file_use_node = symbol_table.lookup_symbol(name, namespace)
              except symbols.Error:
                  return
  
              name = file_use_node[1].filename
              if file_use_node[1].ast_list is None:
                  decl_uses[name] |= USES_REFERENCE
              elif name in file_uses:
                  # enum and typedef can't be forward declared
                  if isinstance(file_use_node[0], (ast.Enum, ast.Typedef)):
                      file_uses[name] |= USES_DECLARATION
                  else:
                      file_uses[name] |= USES_REFERENCE
  
          def _add_use(node, namespace, name=''):
              if isinstance(node, basestring):
                  name = node
              elif isinstance(node, list):
                  # name contains a list of tokens.
                  name = '::'.join([n.name for n in name])
  
              # node is a Type so look for its symbol immediately.
              if name:
                  _do_lookup(name, namespace)
                  return
  
              # Try to search for the value of the variable declaration for any
              # symbols, such as `#define` values or other variable names which
              # may be included in other files.
              obj = getattr(node, 'initial_value', None)
              if obj:
                  _do_lookup(obj, namespace)
  
              # If node is a VariableDeclaration, check if the variable type is
              # a symbol used in other includes.
              obj = getattr(node, 'type', None)
              if obj and isinstance(obj.name, basestring):
                  _do_lookup(obj.name, namespace)
  
              if not isinstance(node, basestring):
                  # Happens when variables are defined with inlined types, e.g.:
                  #   enum {...} variable;
                  return
  
          def _add_variable(node, namespace, reference=False):
              obj = node.type if isinstance(
                  node, ast.VariableDeclaration) else node
  
              if obj.reference or obj.pointer or reference:
                  _add_reference(obj.name, namespace)
              else:
                  # Add a use for the variable declaration type as well as the
                  # variable value.
                  _add_use(obj.name, namespace)
                  _add_use(node, namespace)
              # This needs to recurse when the node is a templated type.
              _add_template_use(obj.name,
                                obj.templated_types,
                                namespace,
                                reference)
  
          def _process_function(function, namespace):
              reference = function.body is None
              if function.return_type:
                  return_type = function.return_type
                  _add_variable(return_type, namespace, reference)
  
              for s in function.specializations:
                  _add_variable(s, namespace, not function.body)
  
              templated_types = function.templated_types or ()
              for p in function.parameters:
                  node = p.type
                  if node.name not in templated_types:
                      if function.body and p.name:
                          # Assume that if the function has a body and a name
                          # the parameter type is really used.
                          # NOTE(nnorwitz): this is over-aggressive. It would be
                          # better to iterate through the body and determine
                          # actual uses based on local vars and data members
                          # used.
                          _add_use(node.name, namespace)
                      elif (
                          p.default and
                          p.default[0].name != '0' and
                          p.default[0].name != 'NULL' and
                          p.default[0].name != 'nullptr'
                      ):
                          _add_use(node.name, namespace)
                      elif node.reference or node.pointer or reference:
                          _add_reference(node.name, namespace)
                      else:
                          _add_use(node.name, namespace)
                      _add_template_use(node.name,
                                        node.templated_types,
                                        namespace,
                                        reference)
  
          def _process_function_body(function, namespace):
              previous = None
              save = namespace[:]
              for t in function.body:
                  if t.token_type == tokenize.NAME:
                      previous = t
                      if not keywords.is_keyword(t.name):
                          # TODO(nnorwitz): handle static function calls.
                          # TODO(nnorwitz): handle using statements in file.
                          # TODO(nnorwitz): handle using statements in function.
                          # TODO(nnorwitz): handle namespace assignment in file.
                          _add_use(t.name, namespace)
                  elif t.name == '::' and previous is not None:
                      namespace.append(previous.name)
                  elif t.name in (':', ';'):
                      namespace = save[:]
  
          def _add_template_use(name, types, namespace, reference=False):
              for cls in types or ():
                  if cls.pointer or cls.reference or reference:
                      _add_reference(cls.name, namespace)
                  elif name.endswith('_ptr'):
                      # Special case templated classes that end w/_ptr.
                      # These are things like auto_ptr which do
                      # not require the class definition, only decl.
                      _add_reference(cls.name, namespace)
                  elif name.startswith('Q') and name.endswith('Pointer'):
                      # Special case templated classes from the Qt framework.
                      _add_reference(cls.name, namespace)
                  else:
                      _add_use(cls.name, namespace)
                  _add_template_use(cls.name, cls.templated_types,
                                    namespace, reference)
  
          def _process_types(nodes, namespace):
              for node in nodes:
                  if isinstance(node, ast.Type):
                      _add_variable(node, namespace)
  
          # Iterate through the source AST/tokens, marking each symbols use.
          ast_seq = [self.ast_list]
          namespace_stack = []
          while ast_seq:
              for node in ast_seq.pop():
                  if isinstance(node, ast.VariableDeclaration):
                      namespace = namespace_stack + node.namespace
                      _add_variable(node, namespace)
                  elif isinstance(node, ast.Function):
                      namespace = namespace_stack + node.namespace
                      _process_function(node, namespace)
                      if node.body:
                          _process_function_body(node, namespace)
                  elif isinstance(node, ast.Typedef):
                      namespace = namespace_stack + node.namespace
                      _process_types(node.alias, namespace)
                  elif isinstance(node, ast.Friend):
                      expr = node.expr
                      namespace = namespace_stack + node.namespace
                      if isinstance(expr, ast.Type):
                          _add_reference(expr.name, namespace)
                      elif isinstance(expr, ast.Function):
                          _process_function(expr, namespace)
                  elif isinstance(node, ast.Union) and node.body is not None:
                      ast_seq.append(node.body)
                  elif isinstance(node, ast.Class) and node.body is not None:
                      _add_declaration(node.name, node.namespace)
                      namespace = namespace_stack + node.namespace
                      _add_template_use('', node.bases, namespace)
                      ast_seq.append(node.body)
                  elif isinstance(node, ast.Using):
                      if node.names[0].name == 'namespace':
                          namespace_stack.append(node.names[1].name)
  
          return file_uses, decl_uses