diff --git a/src/plugins/wp/register.ml b/src/plugins/wp/register.ml
index 206b3d7609d9d16496e2d701dc64c5dabf1ea3e0..89998c9ea08bb99f08e0d3fa2a4d45ff8d4359bf 100644
--- a/src/plugins/wp/register.ml
+++ b/src/plugins/wp/register.ml
@@ -225,6 +225,8 @@ let clear_scheduled () =
     exercised := 0 ;
     session := GOALS.empty ;
     provers := PM.empty ;
+    WpAnnot.unreachable_proved := 0 ;
+    WpAnnot.unreachable_failed := 0 ;
   end
 
 let get_pstat p =
@@ -255,7 +257,6 @@ let add_time s t =
     end
 
 let do_list_scheduled goals =
-  clear_scheduled () ;
   Bag.iter
     (fun goal ->
        begin
@@ -503,25 +504,27 @@ let do_report_scheduled () =
     let plural = if !exercised > 1 then "s" else "" in
     Wp_parameters.result "%d goal%s generated" !exercised plural
   else
-  if !scheduled > 0 then
-    begin
-      let passed = GOALS.fold
-          (fun g n ->
-             if Wpo.is_passed g then succ n else n
-          ) !session 0 in
-      let mode = Cache.get_mode () in
-      if mode <> Cache.NoCache then do_report_cache_usage mode ;
-      Wp_parameters.result "%t"
-        begin fun fmt ->
-          Format.fprintf fmt "Proved goals: %4d / %d@\n" passed !scheduled ;
-          Pretty_utils.pp_items
-            ~min:12 ~align:`Left
-            ~title:(fun (prover,_) -> VCS.title_of_prover prover)
-            ~iter:(fun f -> PM.iter (fun p s -> f (p,s)) !provers)
-            ~pp_title:(fun fmt a -> Format.fprintf fmt "%s:" a)
-            ~pp_item:do_report_prover_stats fmt ;
-        end ;
-    end
+    let total =
+      !scheduled + !WpAnnot.unreachable_failed + !WpAnnot.unreachable_proved in
+    if total > 0 then
+      begin
+        let passed = GOALS.fold
+            (fun g n ->
+               if Wpo.is_passed g then succ n else n
+            ) !session !WpAnnot.unreachable_proved in
+        let mode = Cache.get_mode () in
+        if mode <> Cache.NoCache then do_report_cache_usage mode ;
+        Wp_parameters.result "%t"
+          begin fun fmt ->
+            Format.fprintf fmt "Proved goals: %4d / %d@\n" passed total ;
+            Pretty_utils.pp_items
+              ~min:12 ~align:`Left
+              ~title:(fun (prover,_) -> VCS.title_of_prover prover)
+              ~iter:(fun f -> PM.iter (fun p s -> f (p,s)) !provers)
+              ~pp_title:(fun fmt a -> Format.fprintf fmt "%s:" a)
+              ~pp_item:do_report_prover_stats fmt ;
+          end ;
+      end
 
 let do_list_scheduled_result () =
   begin
diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/nupw-bcl-bts1120.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/nupw-bcl-bts1120.res.oracle
index 164271bc40ab026c97fa2a3ab4579fcb40c49bda..b7eb301f1182c82ee5e56750240487d8a1b2d157 100644
--- a/src/plugins/wp/tests/wp_bts/oracle_qualif/nupw-bcl-bts1120.res.oracle
+++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/nupw-bcl-bts1120.res.oracle
@@ -17,7 +17,7 @@
 [wp] [Qed] Goal typed_g_assigns_normal_part3 : Valid
 [wp] [Qed] Goal typed_unreachable_smt_with_contract_ensures_ok_2 : Valid
 [wp] [Qed] Goal typed_unreachable_smt_with_contract_call_f_with_precond_2_requires_ok : Valid
-[wp] Proved goals:    8 / 8
+[wp] Proved goals:   14 / 14
   Qed:             8
 ------------------------------------------------------------
  Functions                 WP     Alt-Ergo  Total   Success
diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/string-compare.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/string-compare.res.oracle
index 48ad48fb860195d2301df4b58092b1e8086305dc..98114b8eb4713eda59a07effdbde20813a2eea86 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/string-compare.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/string-compare.res.oracle
@@ -56,7 +56,7 @@
 [wp] [Qed] Goal typed_main_assigns_normal_part1 : Valid
 [wp] [Qed] Goal typed_main_assigns_normal_part2 : Valid
 [wp] [Alt-Ergo] Goal typed_main_call_stringCompare_requires_validStrings : Valid
-[wp] Proved goals:   51 / 51
+[wp] Proved goals:   53 / 53
   Qed:            33 
   Alt-Ergo:       18
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_plugin/doomed_dead.i b/src/plugins/wp/tests/wp_plugin/doomed_dead.i
index 5cba4b4ae13d297cf591afaa08431a1c45694e41..8d0d1b2c50fc6f8e06c5e79012073da85f98f6b9 100644
--- a/src/plugins/wp/tests/wp_plugin/doomed_dead.i
+++ b/src/plugins/wp/tests/wp_plugin/doomed_dead.i
@@ -3,8 +3,8 @@
  */
 
 /* run.config_qualif
-   OPT: -wp-smoke-tests
-   OPT: -wp-smoke-tests -wp-split
+   OPT: -wp-smoke-tests -wp-steps 100
+   OPT: -wp-smoke-tests -wp-steps 100 -wp-split
 */
 
 //@ assigns \nothing ;
diff --git a/src/plugins/wp/tests/wp_plugin/doomed_unreach.i b/src/plugins/wp/tests/wp_plugin/doomed_unreach.i
new file mode 100644
index 0000000000000000000000000000000000000000..6327fad4ec08aa62ba356fd50696547c3400b4c9
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/doomed_unreach.i
@@ -0,0 +1,24 @@
+/* run.config
+   DONTRUN:
+ */
+
+/* run.config_qualif
+   OPT: -wp-smoke-tests -wp-steps 100
+*/
+
+//@ assigns \result;
+int job(int x) {
+  switch(x) {
+    return 42;
+  case 0:
+    return 0;
+  case 1:
+    return 1;
+    x = 42;
+    return 42;
+  default:
+    return 3;
+  }
+  x = 42;
+  return 42;
+}
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.0.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.0.res.oracle
index 0b349526c40d14e9bc6ee38bd5e6574999977b81..882ac924345c75bfbe007ec974f073762e8e6381 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.0.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.0.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp [...]
+# frama-c -wp -wp-steps 100 [...]
 [kernel] Parsing tests/wp_plugin/doomed_dead.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle
index fd8fae824785bcd829b66d0b40756567adba02b3..f3a71acd41e49cfc63ac7dcd2803443c07296812 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-split [...]
+# frama-c -wp -wp-split -wp-steps 100 [...]
 [kernel] Parsing tests/wp_plugin/doomed_dead.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_unreach.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_unreach.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7140362d3548372aa5cbc7e8ff1bc89cf34acbf4
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_unreach.res.oracle
@@ -0,0 +1,21 @@
+# frama-c -wp -wp-steps 100 [...]
+[kernel] Parsing tests/wp_plugin/doomed_unreach.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] tests/wp_plugin/doomed_unreach.i:12: Warning: Failed smoke-test
+[wp] tests/wp_plugin/doomed_unreach.i:17: Warning: Failed smoke-test
+[wp] tests/wp_plugin/doomed_unreach.i:22: Warning: Failed smoke-test
+[wp] Warning: Missing RTE guards
+[wp] 6 goals scheduled
+[wp] [Passed] Smoke-test typed_job_wp_smoke_dead_code_s4
+[wp] [Passed] Smoke-test typed_job_wp_smoke_dead_code_s5
+[wp] [Passed] Smoke-test typed_job_wp_smoke_dead_code_s8
+[wp] [Qed] Goal typed_job_assigns_part1 : Valid
+[wp] [Qed] Goal typed_job_assigns_part2 : Valid
+[wp] [Qed] Goal typed_job_assigns_part3 : Valid
+[wp] Proved goals:    6 / 9
+  Qed:             3 
+  Alt-Ergo:        3
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  job                       3        3        6       100%
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.log b/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.log
index 583f4d36f0886bdb9e400a01be8bc0d7723ec389..54fa701c499fd123bd6160f72a022ee8b5fd21de 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.log
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.log
@@ -19,3 +19,4 @@
 [wp] CFG f -> f
 [wp] CFG f -> f_default_for_stmt_2
 [wp] Warning: No goal generated
+[wp] Proved goals:    9 / 9
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.res.oracle
index 3a74fac104c542c05e02bcaa5acab1560cebf58a..0d904ff5c08035bbca30031d490eb15e6ffdf0f0 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/stmt.res.oracle
@@ -22,7 +22,7 @@
 [wp] [Qed] Goal typed_h_ensures_2 : Valid
 [wp] [Qed] Goal typed_h_assert : Valid
 [wp] [Qed] Goal typed_h_assert_2 : Valid
-[wp] Proved goals:   10 / 10
+[wp] Proved goals:   19 / 19
   Qed:            10
 ------------------------------------------------------------
  Functions                 WP     Alt-Ergo  Total   Success
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.0.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.0.res.oracle
index 3945dd8f3a65ec11fffa0303fe8300c4c4e63a66..890545f1a901bbb0eaec681155b688d75658e609 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.0.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.0.res.oracle
@@ -100,7 +100,7 @@
 [wp] [Qed] Goal typed_init_t2_bis_v2_loop_variant_positive : Valid
 [wp] [Qed] Goal typed_init_t2_bis_v2_call_init_requires : Valid
 [wp] [Qed] Goal typed_init_t2_bis_v2_call_init_requires_2 : Valid
-[wp] Proved goals:   92 / 92
+[wp] Proved goals:   97 / 97
   Qed:            52 
   Alt-Ergo:       40
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle
index f9f0f2c219867828a57bba71fbce2fade387cf24..71a1c37ecc6fac5af4a88d1151b8798d141a3ca8 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle
@@ -31,7 +31,7 @@
 [wp] [Qed] Goal typed_init_t2_bis_v2_assigns_exit_part3 : Valid
 [wp] [Qed] Goal typed_init_t2_bis_v2_assigns_normal_part1 : Valid
 [wp] [Script] Goal typed_init_t2_bis_v2_assigns_normal_part2 : Valid
-[wp] Proved goals:   23 / 23
+[wp] Proved goals:   28 / 28
   Qed:            11 
   Script:         12 
   Alt-Ergo:        0  (unsuccess: 12)
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.2.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.2.res.oracle
index 41f563dd7bf77dbfd732205c343f841b0bad0caf..73b6604f313f1b3c18ba90b8824a3f4c14e24982 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.2.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.2.res.oracle
@@ -24,7 +24,7 @@
 [wp] [Qed] Goal typed_init_t2_bis_v1_assigns_exit_part3 : Valid
 [wp] [Qed] Goal typed_init_t2_bis_v1_assigns_normal_part1 : Valid
 [wp] [Alt-Ergo] Goal typed_init_t2_bis_v1_assigns_normal_part2 : Unsuccess
-[wp] Proved goals:    7 / 16
+[wp] Proved goals:   12 / 21
   Qed:             7 
   Alt-Ergo:        0  (unsuccess: 9)
 ------------------------------------------------------------
diff --git a/src/plugins/wp/wpAnnot.ml b/src/plugins/wp/wpAnnot.ml
index c27e5f587c1c40a375e52e7aed7d072cc4565844..4a8f6ea3aeadb06a0fde85baa9c1bc075daec05b 100644
--- a/src/plugins/wp/wpAnnot.ml
+++ b/src/plugins/wp/wpAnnot.ml
@@ -68,6 +68,9 @@ let get_called_assigns kf =
 (* --- Status of Unreachable Annotations                                  --- *)
 (* -------------------------------------------------------------------------- *)
 
+let unreachable_proved = ref 0
+let unreachable_failed = ref 0
+
 let wp_unreachable =
   Emitter.create
     "Unreachable Annotations"
@@ -76,27 +79,36 @@ let wp_unreachable =
     ~tuning:[] (* TBC *)
 
 let set_unreachable pid =
-  let open Property in
-  let emit = function
-    | IPPredicate {ip_kind = PKAssumes _} -> ()
-    | p ->
-        debug "unreachable annotation %a@." Property.pretty p;
-        Property_status.emit wp_unreachable ~hyps:[] p Property_status.True
-  in
-  let pids = match WpPropId.property_of_id pid with
-    | IPPredicate {ip_kind = PKAssumes _} -> []
-    | IPBehavior {ib_kf; ib_kinstr; ib_active; ib_bhv} ->
-        let active = Datatype.String.Set.elements ib_active in
-        (ip_post_cond_of_behavior ib_kf ib_kinstr active ib_bhv) @
-        (ip_requires_of_behavior ib_kf ib_kinstr ib_bhv)
-    | IPExtended _ -> []
-    (* Extended clauses might concern anything. Don't validate them
-       unless we know exactly what is going on. *)
-    | p ->
-        Wp_parameters.result "[CFG] Goal %a : Valid (Unreachable)"
-          WpPropId.pp_propid pid ; [p]
-  in
-  List.iter emit pids
+  if WpPropId.is_smoke_test pid then
+    begin
+      let source = WpPropId.source_of_id pid in
+      WpReached.set_doomed wp_unreachable pid ;
+      incr unreachable_failed ;
+      Wp_parameters.warning ~source "Failed smoke-test"
+    end
+  else
+    let open Property in
+    let emit = function
+      | IPPredicate {ip_kind = PKAssumes _} -> ()
+      | p ->
+          debug "unreachable annotation %a@." Property.pretty p;
+          Property_status.emit wp_unreachable ~hyps:[] p Property_status.True
+    in
+    let pids = match WpPropId.property_of_id pid with
+      | IPPredicate {ip_kind = PKAssumes _} -> []
+      | IPBehavior {ib_kf; ib_kinstr; ib_active; ib_bhv} ->
+          let active = Datatype.String.Set.elements ib_active in
+          (ip_post_cond_of_behavior ib_kf ib_kinstr active ib_bhv) @
+          (ip_requires_of_behavior ib_kf ib_kinstr ib_bhv)
+      | IPExtended _ -> []
+      (* Extended clauses might concern anything. Don't validate them
+         unless we know exactly what is going on. *)
+      | p ->
+          incr unreachable_proved ;
+          Wp_parameters.result "[CFG] Goal %a : Valid (Unreachable)"
+            WpPropId.pp_propid pid ; [p]
+    in
+    List.iter emit pids
 
 (*----------------------------------------------------------------------------*)
 (* Proofs                                                                     *)
@@ -238,7 +250,7 @@ module HdefAnnotBhv = Cil2cfg.HE (struct type t = (stmt * int) end)
 type strategy_info = {
   kf : Kernel_function.t;
   cfg : Cil2cfg.t;
-  reached : WpReached.reached option ;
+  reachability : WpReached.reachability option ;
   cur_bhv : asked_bhv;
   asked_bhvs : asked_bhv list;
   asked_prop : asked_prop;
@@ -915,7 +927,7 @@ let get_loop_annots config vloop s =
 let add_stmt_deadcode_smoke config acc s =
   if cur_fct_default_bhv config
   then
-    match config.reached with
+    match config.reachability with
     | Some r when WpReached.smoking r s ->
         WpStrategy.add_prop_dead_code acc config.kf s
     | _ -> acc
@@ -1282,7 +1294,7 @@ class vexit kf acc =
       Cil.DoChildren
   end
 
-let process_unreached_annots cfg =
+let process_unreached_annots cfg reachability =
   debug "collecting unreachable annotations@.";
   let unreached = Cil2cfg.unreachable_nodes cfg in
   let kf = Cil2cfg.cfg_kf cfg in
@@ -1298,6 +1310,16 @@ let process_unreached_annots cfg =
   let do_annot s _ a acc =
     List.fold_left add_id acc (WpPropId.mk_code_annot_ids kf s a)
   in
+  let do_stmt s acc =
+    let acc =
+      match reachability with
+      | None -> acc
+      | Some r ->
+          if WpReached.smoking r s then
+            WpPropId.mk_smoke kf ~id:"unreachable" ~unreachable:s () :: acc
+          else acc
+    in Annotations.fold_code_annot (do_annot s) s acc
+  in
   let do_node acc n =
     debug
       "process annotations of unreachable node %a@."
@@ -1312,13 +1334,13 @@ let process_unreached_annots cfg =
         ignore Visitor.(visitFramacKf (visitor :> frama_c_visitor) kf) ;
         visitor#acc
     | Cil2cfg.Vcall (s, _, call, _) ->
-        Annotations.fold_code_annot (do_annot s) s acc @
+        do_stmt s acc @
         preconditions_at_call s call
     | Cil2cfg.Vstmt s
     | Cil2cfg.VblkIn (Cil2cfg.Bstmt s, _)
     | Cil2cfg.VblkOut (Cil2cfg.Bstmt s, _)
     | Cil2cfg.Vtest (true, s, _) | Cil2cfg.Vloop (_, s) | Cil2cfg.Vswitch (s,_)
-      -> Annotations.fold_code_annot (do_annot s) s acc
+      -> do_stmt s acc
     | Cil2cfg.Vtest (false, _, _) | Cil2cfg.Vloop2 _
     | Cil2cfg.VblkIn _ | Cil2cfg.VblkOut _ | Cil2cfg.Vend -> acc
   in
@@ -1330,11 +1352,6 @@ let process_unreached_annots cfg =
 (* Everything must go through here.                                           *)
 (*----------------------------------------------------------------------------*)
 
-let get_cfg kf model =
-  if Wp_parameters.RTE.get () then WpRTE.generate model kf ;
-  let cfg = Cil2cfg.get kf in
-  let _ = process_unreached_annots cfg in cfg
-
 let build_configs assigns kf model behaviors ki property =
   debug "[get_strategies] for behaviors names: %a@."
     (Wp_error.pp_string_list ~sep:" " ~empty:"<none>")
@@ -1348,16 +1365,18 @@ let build_configs assigns kf model behaviors ki property =
         debug
           "[get_strategies] select stmt %d properties@." s.sid
   in
-  let cfg = get_cfg kf model in
-  let reached =
+  if Wp_parameters.RTE.get () then WpRTE.generate model kf ;
+  let cfg = Cil2cfg.get kf in
+  let reachability =
     if Wp_parameters.SmokeTests.get ()
     && Wp_parameters.SmokeDeadcode.get ()
-    then Some (WpReached.reached kf)
+    then Some (WpReached.reachability kf)
     else None in
+  process_unreached_annots cfg reachability ;
   let def_annot_bhv, bhvs = find_behaviors kf cfg ki behaviors in
   if bhvs <> [] then debug "[get_strategies] %d behaviors" (List.length bhvs);
   let mk_bhv_config bhv = {
-    kf; reached; cfg;
+    kf; reachability; cfg;
     cur_bhv = bhv;
     asked_prop = property;
     asked_bhvs = bhvs;
diff --git a/src/plugins/wp/wpAnnot.mli b/src/plugins/wp/wpAnnot.mli
index fdd66f1de807146ead86fec1bf891ca75b0ebd5c..a005a5d2c36b54c29e3921a894615094f3333242 100644
--- a/src/plugins/wp/wpAnnot.mli
+++ b/src/plugins/wp/wpAnnot.mli
@@ -56,6 +56,9 @@ val filter_status : WpPropId.prop_id -> bool
 
 (*----------------------------------------------------------------------------*)
 
+val unreachable_proved : int ref
+val unreachable_failed : int ref
+
 val get_called_preconditions_at : kernel_function -> stmt -> Property.t list
 val get_called_post_conditions : kernel_function -> Property.t list
 val get_called_exit_conditions : kernel_function -> Property.t list
diff --git a/src/plugins/wp/wpReached.ml b/src/plugins/wp/wpReached.ml
index b21fa463f9fdd3b9aae169f4c37799a80600c8d0..60fe40d175ef9651652217627cc829397fddd8c9 100644
--- a/src/plugins/wp/wpReached.ml
+++ b/src/plugins/wp/wpReached.ml
@@ -40,14 +40,20 @@ type node = {
   id : int ;
   mutable flow : flow ;
   mutable prev : node list ;
-  mutable reached : bool option ;
+  mutable protected : bool option ;
+  (* whether the node is dominated by unreachable node or by a smoke test *)
+  mutable unreachable : bool option ;
+  (* whether the node is unreachable from the entry point *)
 }
 
 let kid = ref 0
 
 let node () =
   incr kid ;
-  { id = !kid ; prev = [] ; reached = None ; flow = F_goto }
+  { id = !kid ; prev = [] ;
+    protected = None ;
+    unreachable = None ;
+    flow = F_goto }
 
 (* -------------------------------------------------------------------------- *)
 (* --- Unrolled Loop                                                      --- *)
@@ -83,7 +89,7 @@ let rec is_predicate cond p =
 let is_dead_annot ca =
   match ca.annot_content with
   | APragma (Loop_pragma (Unroll_specs [ spec ; _ ])) ->
-      false && is_unrolled_completely spec
+      is_unrolled_completely spec
   | AAssert([],p)
   | AInvariant([],_,p) ->
       not p.tp_only_check && is_predicate false p.tp_statement
@@ -102,8 +108,8 @@ let is_dead_code stmt =
 (* --- Compute CFG                                                        --- *)
 (* -------------------------------------------------------------------------- *)
 
-type reached = node Stmt.Map.t
-type cfg = reached ref
+type reachability = node Stmt.Map.t
+type cfg = reachability ref (* working cfg during compilation *)
 
 let of_stmt cfg s =
   try Stmt.Map.find s !cfg with Not_found ->
@@ -133,11 +139,8 @@ type env = {
 
 let rec stmt env s b =
   let a = of_stmt env.cfg s in
-  if is_dead_code s then
-    a.flow <- F_dead
-  else
-    a.flow <- skind env a b s.skind ;
-  a
+  let f = skind env a b s.skind in
+  a.flow <- if is_dead_code s then F_dead else f ; a
 
 and skind env a b = function
   | Instr i -> flow i (goto a b)
@@ -177,29 +180,46 @@ and sequence env seq b = match seq with
 (* --- Compute Reachability                                               --- *)
 (* -------------------------------------------------------------------------- *)
 
-let rec reached node =
-  match node.reached with
+let rec unreachable node =
+  match node.unreachable with
   | Some r -> r
   | None ->
-      node.reached <- Some true ; (* cut loops *)
-      let r = List.for_all reached_after node.prev in
-      node.reached <- Some r ; r
-
-and reached_after node =
-  match node.flow with
-  | F_goto -> reached node
-  | F_effect | F_entry | F_dead -> true
-  | F_return | F_branch | F_call -> false
+      node.unreachable <- Some true ; (* cut loops *)
+      let r =
+        match node.flow with
+        | F_dead -> true
+        | F_entry -> false
+        | F_goto | F_effect | F_return | F_branch | F_call ->
+            List.for_all unreachable node.prev
+      in node.unreachable <- Some r ; r
+
+let rec protected node =
+  match node.protected with
+  | Some r -> r
+  | None ->
+      node.protected <- Some false ; (* cut loops *)
+      let r =
+        match node.flow with
+        | F_dead | F_entry -> true
+        | F_goto | F_effect | F_return | F_branch | F_call ->
+            node.prev <> [] && List.for_all protected_by node.prev
+      in node.protected <- Some r ; r
+
+and protected_by prev =
+  match prev.flow with
+  | F_dead | F_entry | F_effect -> true
+  | F_goto -> protected prev
+  | F_call | F_branch | F_return -> unreachable prev
 
 let smoking_node n =
   match n.flow with
-  | F_effect | F_call | F_return -> not (reached n)
+  | F_effect | F_call | F_return -> not (protected n)
   | F_goto | F_branch | F_entry | F_dead -> false
 
 (* returns true if the stmt requires a reachability smoke test *)
-let smoking nodes stmt =
-  try Stmt.Map.find stmt nodes |> smoking_node
-  with Not_found -> false
+let smoking reachability stmt =
+  try Stmt.Map.find stmt reachability |> smoking_node
+  with Not_found -> true
 
 let compute kf =
   try
@@ -230,14 +250,10 @@ let dump ~dir kf reached =
   N.define dot
     (fun a na ->
        let attr =
-         if smoking_node a
-         then [`Filled;`Fillcolor "orange"]
-         else
-           match a.flow with
-           | F_entry | F_effect | F_return | F_call ->
-               [`Filled;`Fillcolor "green"]
-           | F_dead -> [`Filled;`Fillcolor "red"]
-           | F_branch | F_goto -> []
+         if smoking_node a then [`Filled;`Fillcolor "orange"]
+         else if protected a then [`Filled;`Fillcolor "green"]
+         else if unreachable a then [`Filled;`Fillcolor "red"]
+         else []
        in G.node dot na attr ;
        List.iter
          (fun b ->
@@ -262,7 +278,8 @@ let dump ~dir kf reached =
          | UnspecifiedSequence  _ -> Printf.sprintf "Seq. s%d" s.sid
          | Throw _ | TryExcept _ | TryCatch _ | TryFinally _ ->
              Printf.sprintf "Exn. s%d" s.sid
-       in G.node dot (N.get n) [`Box;`Label label])
+       in G.node dot (N.get n)
+         [`Box;`Label (Printf.sprintf "s%d n%d: %s" s.sid n.id label)])
     reached ;
   G.run dot ;
   G.close dot ;
@@ -276,7 +293,7 @@ let dump ~dir kf reached =
 module FRmap = Kernel_function.Make_Table
     (Datatype.Make
        (struct
-         type t = reached
+         type t = reachability
          include Datatype.Serializable_undefined
          let reprs = [Stmt.Map.empty]
          let name = "WpReachable.reached"
@@ -289,7 +306,7 @@ module FRmap = Kernel_function.Make_Table
 
 let dkey = Wp_parameters.register_category "reached"
 
-let reached = FRmap.memo
+let reachability = FRmap.memo
     begin fun kf ->
       let r = compute kf in
       (if Wp_parameters.has_dkey dkey then
@@ -298,3 +315,28 @@ let reached = FRmap.memo
     end
 
 (* -------------------------------------------------------------------------- *)
+(* --- Doome Status                                                       --- *)
+(* -------------------------------------------------------------------------- *)
+
+let set_invalid emitter tgt =
+  Property_status.emit emitter ~hyps:[] tgt Property_status.False_if_reachable
+
+let set_doomed emitter pid =
+  List.iter (set_invalid emitter) (WpPropId.doomed_if_valid pid) ;
+  match WpPropId.unreachable_if_valid pid with
+  | Property.OLStmt(kf,stmt) ->
+      let ca =
+        match Annotations.code_annot ~emitter ~filter:is_dead_annot stmt with
+        | ca::_ -> ca
+        | [] ->
+            let pred_loc = Stmt.loc stmt in
+            let pred_name = [ "Wp" ; "SmokeTest" ] in
+            let pf = { Logic_const.pfalse with pred_loc ; pred_name } in
+            let pf = Logic_const.toplevel_predicate pf in
+            let ca = Logic_const.new_code_annotation (AAssert ([],pf)) in
+            Annotations.add_code_annot emitter ~kf stmt ca ; ca
+      in
+      List.iter (set_invalid emitter) (Property.ip_of_code_annot kf stmt ca)
+  | Property.OLGlob _ | Property.OLContract _ -> ()
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/wpReached.mli b/src/plugins/wp/wpReached.mli
index 2f7bc0283bc0c5cc24c0cdd7d6984cf1c3d40c95..2ef8a243c65a83a8e890e6eeed02a99c213cdbb4 100644
--- a/src/plugins/wp/wpReached.mli
+++ b/src/plugins/wp/wpReached.mli
@@ -26,7 +26,7 @@
 
 open Cil_types
 
-type reached
+type reachability
 (** control flow graph dedicated to smoke tests *)
 
 val is_predicate : bool -> predicate -> bool
@@ -39,14 +39,16 @@ val is_dead_annot : code_annotation -> bool
 val is_dead_code : stmt -> bool
 (** Checks whether the stmt has a dead-code annotation. *)
 
-val reached : Kernel_function.t -> reached
+val reachability : Kernel_function.t -> reachability
 (** memoized reached cfg for function *)
 
-val smoking : reached -> Cil_types.stmt -> bool
+val smoking : reachability -> Cil_types.stmt -> bool
 (** Returns whether a stmt need a smoke tests to avoid being unreachable.
     This is restricted to assignments, returns and calls not dominated
     another smoking statement. *)
 
-val dump : dir:Datatype.Filepath.t -> Kernel_function.t -> reached -> unit
+val dump : dir:Datatype.Filepath.t -> Kernel_function.t -> reachability -> unit
+
+val set_doomed : Emitter.t -> WpPropId.prop_id -> unit
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/wpo.ml b/src/plugins/wp/wpo.ml
index e5459e75b894fda2a88fd783408471bef27d773b..bed4b06b77b25790f7c8b8c259dafcaee4d48878 100644
--- a/src/plugins/wp/wpo.ml
+++ b/src/plugins/wp/wpo.ml
@@ -715,28 +715,6 @@ let get_proof g =
     with Not_found -> `Unknown
   in status , target
 
-let set_invalid emitter tgt =
-  Property_status.emit emitter ~hyps:[] tgt Property_status.False_if_reachable
-
-let set_doomed emitter pid =
-  List.iter (set_invalid emitter) (WpPropId.doomed_if_valid pid) ;
-  match WpPropId.unreachable_if_valid pid with
-  | Property.OLStmt(kf,stmt) ->
-      let ca =
-        let filter = WpReached.is_dead_annot in
-        match Annotations.code_annot ~emitter ~filter stmt with
-        | ca::_ -> ca
-        | [] ->
-            let pred_loc = Stmt.loc stmt in
-            let pred_name = [ "Wp" ; "SmokeTest" ] in
-            let pf = { Logic_const.pfalse with pred_loc ; pred_name } in
-            let pf = Logic_const.toplevel_predicate pf in
-            let ca = Logic_const.new_code_annotation (AAssert ([],pf)) in
-            Annotations.add_code_annot emitter ~kf stmt ca ; ca
-      in
-      List.iter (set_invalid emitter) (Property.ip_of_code_annot kf stmt ca)
-  | Property.OLGlob _ | Property.OLContract _ -> ()
-
 let find_proof system g =
   let pi = proof g (WpPropId.property_of_id g.po_pid) in
   try Hproof.find system.proofs pi
@@ -789,7 +767,7 @@ let set_result g p r =
       in
       let hyps = if smoke then [] else WpAnnot.dependencies proof in
       Property_status.emit emitter ~hyps target status ;
-      if smoke && unproved && proved then set_doomed emitter g.po_pid ;
+      if smoke && unproved && proved then WpReached.set_doomed emitter g.po_pid ;
   end
 
 let has_verdict g p =