let rec status_of_deps values state =
      if S.use_ctrl_dependencies && !last_stmt != dummyStmt then begin
        let stmt = !last_stmt in
        let _, kf = Kernel_function.find_from_sid stmt.sid in
        let pdg = !Pdg.get kf in
(*        log "stmt %a@." d_stmt stmt;*)
        let nodes = !Pdg.find_simple_stmt_nodes pdg stmt in
        let deps =
          match nodes with
          | [] -> []
          | n :: _ -> !Pdg.direct_ctrl_dpds pdg n
        in
(*        List.iter (fun n -> log "node %a@." !Pdg.pretty_node n) deps;*)
        let status_of_dep dep =
          (* search the expression of the statement which really is the control
             dependence and compute its status *)

          match dep.skind with
          | If(e, _, _, _) | Switch(e, _, _, _) ->
              find_exp_status ~with_deps:false values state e
          | Block _ | UnspecifiedSequence _
          | Instr (Asm _) (* because of possible dummyStmt, see below *) ->
              S.bottom
          | _ ->
              assert false
        in
        List.fold_left
          (fun acc n ->
             let s =
               match !Pdg.node_key n with
               | PdgIndex.Key.Stmt s -> s
               | PdgIndex.Key.SigCallKey (_id,
                   (PdgIndex.Signature.In PdgIndex.Signature.InCtrl)) ->
                    dummyStmt (* TODO: Anne. *)
               | PdgIndex.Key.SigKey _k -> dummyStmt (* TODO: huh, very ugly *)
               | _ ->
                   Options.fatal "unknown PDG key: %a"
                     PdgIndex.Key.pretty (!Pdg.node_key n)
             in
             S.join acc (status_of_dep s))
          (* continue the current dependencies computation *)
          (try (Stack.top call_stack).deps with Stack.Empty -> S.bottom)
          deps
      end else
        S.bottom

    and join_deps values state = S.join (status_of_deps values state)

    and find_loc_or_status ?(with_deps=true) values state e =
      let status s =
        Status
          (if with_deps then S.join s (status_of_deps values state) else s)
      in
      match (stripInfo e).enode with
      | Info _ -> assert false
      | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ ->
          status S.constant
      | Lval lv ->
          let e, subst_occured = Subst.lval ~trans:true lv state.subst in
          if subst_occured then
            find_loc_or_status ~with_deps values state e
          else
            Location (lval_to_loc values lv)
      | AddrOf _lv | StartOf _lv ->
          (* TODO: Flyspray #64 *)
          Options.warning ~once:true ~current:true
            "address expression detected: suboptimical case in this version";
          Status S.top
      | CastE(ty, e) ->
          let s = L.type_attributes2state S.bottom ty in
          let ls = find_loc_or_status ~with_deps values state e in
          if S.equal s S.bottom  then
            ls
          else
            (match ls with
             | Status _ ->
                 status s
             | Location l ->
                 status (S.join s (L.snd (find_loc_status state l))))
      | SizeOfE e | AlignOfE e | UnOp(_, e, _) ->
          find_loc_or_status ~with_deps values state e
      | BinOp((PlusPI | IndexPI | MinusPI | MinusPP), _e1, _e2, TPtr _) ->
          (* TODO: Flyspray #64 *)
          Options.warning ~once:true ~current:true
            "arithmetic pointer expression detected: suboptimital case in this version";
          Status S.top
      | BinOp((PlusPI | IndexPI | MinusPI | MinusPP), _e1, _e2, _) ->
          assert false
      | BinOp(_, e1, e2, _) ->
          let s1 = find_exp_status ~with_deps values state e1 in
          let s2 = find_exp_status ~with_deps values state e2 in
          status (S.join s1 s2)

    and find_exp_status ?(with_deps=true) values state e =
      match find_loc_or_status ~with_deps values state e with
      | Status s -> s
      | Location l -> find_loc_status_with_deps ~with_deps state l