diff --git a/src/plugins/wp/cil2cfg.ml b/src/plugins/wp/cil2cfg.ml
index 0afef00829bce0f5af4c9d58aedf3ddf44de2861..7cbbb3103136b9f29f396964e0a240e6fcdcc904 100644
--- a/src/plugins/wp/cil2cfg.ml
+++ b/src/plugins/wp/cil2cfg.ml
@@ -306,6 +306,8 @@ type t = {
   unreachables : node_type list;
   loop_nodes : (node list) option;
   mutable loop_cpt : int;
+  mutable node_break : node option;
+  mutable node_continue : node option;
 }
 
 let new_cfg_env spec_only kf = {
@@ -316,6 +318,8 @@ let new_cfg_env spec_only kf = {
   unreachables = [];
   loop_nodes = None;
   loop_cpt = 0;
+  node_break = None;
+  node_continue = None;
 }
 
 let cfg_kf cfg = cfg.kernel_function
@@ -804,6 +808,15 @@ let get_stmt_node env s =
   | TryExcept _ | TryFinally _ | Throw _ | TryCatch _ ->
       Wp_parameters.not_yet_implemented "[cfg] exception handling"
 
+let cfg_stmt_goto env s next =
+  let node = get_node env (Vstmt s) in
+  add_edge env node Enone next ; node
+
+let get_succ env s =
+  begin match s.succs with
+    | [s'] -> get_stmt_node env s'
+    | _ -> Wp_parameters.fatal "[cfg] jump with more than one successor ?"
+  end
 
 (** build the nodes for the [stmts], connect the last one with [next],
  * and return the node of the first stmt. *)
@@ -827,7 +840,16 @@ and cfg_block env bkind b next =
 and cfg_switch env switch_stmt switch_exp blk case_stmts next =
   let n_switch = get_node env (Vswitch (switch_stmt, switch_exp)) in
   add_edge env n_switch Enext next;
-  let _first = cfg_stmts env blk.bstmts next in
+  begin
+    let s_break = env.node_break in
+    try
+      env.node_break <- Some next ;
+      let _first = cfg_stmts env blk.bstmts next in
+      env.node_break <- s_break ;
+    with e ->
+      env.node_break <- s_break ;
+      raise e
+  end ;
   let branch with_def s =
     let n = get_stmt_node env s in
     let rec find_case l = match l with
@@ -896,22 +918,47 @@ and cfg_stmt env s next =
         n_in
       end
   | Loop(_, b, _, _, _) ->
-      let loop = get_stmt_node env s in
-      add_edge env loop Enext next;
-      let in_b = cfg_block env (Bloop s) b loop in
-      add_edge env loop Enone in_b;
-      loop
-  | Break _ | Continue _ | Goto _ ->
-      let n = get_stmt_node env s in
-      let _ = match s.succs with
-        | [s'] -> add_edge env n Enone (get_stmt_node env s')
-        | _ -> Wp_parameters.fatal "[cfg] jump with more than one successor ?"
-      in n
+      let s_loop = get_stmt_node env s in
+      let b_loop = Bloop s in
+      let s_out = get_node env (VblkOut(b_loop,b)) in
+      let b_in = cfg_block_with
+          ~break:next
+          ~continue:s_out
+          env b_loop b s_loop in
+      add_edge env s_loop Enext next;
+      add_edge env s_loop Enone b_in;
+      s_loop
+  | Break _ ->
+      begin match env.node_break with
+        | None -> Wp_parameters.fatal "[cfg] missing break successor"
+        | Some brk -> cfg_stmt_goto env s brk
+      end
+  | Continue _ ->
+      begin match env.node_continue with
+        | None -> Wp_parameters.fatal "[cfg] missing continue successor"
+        | Some cnt -> cfg_stmt_goto env s cnt
+      end
+  | Goto _ -> cfg_stmt_goto env s (get_succ env s)
   | Switch (e, b, lstmts, _) ->
       cfg_switch env s e b lstmts next
   | TryExcept _ | TryFinally _ | Throw _ | TryCatch _ ->
       Wp_parameters.not_yet_implemented "[cfg] exception handling"
 
+and cfg_block_with ?continue ?break env bkind block next =
+  let s_continue = env.node_continue in
+  let s_break = env.node_break in
+  try
+    if continue <> None then env.node_continue <- continue ;
+    if break <> None then env.node_break <- break ;
+    let head = cfg_block env bkind block next in
+    env.node_continue <- s_continue ;
+    env.node_break <- s_break ;
+    head
+  with e ->
+    env.node_continue <- s_continue ;
+    env.node_break <- s_break ;
+    raise e
+
 (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
 (** {3 Cleaning} remove node and edges that are unreachable *)
 
@@ -1212,6 +1259,53 @@ let very_strange_loops cfg =
 (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
 (** {3 Create CFG} *)
 
+(*
+Debugging code exporting the CFG in DOT:
+
+let pp_node_type_dot fmt = function
+  | Bstmt { sid } -> Format.fprintf fmt "s%d" sid
+  | Bthen { sid } -> Format.fprintf fmt "then_s%d" sid
+  | Belse { sid } -> Format.fprintf fmt "else_s%d" sid
+  | Bloop { sid } -> Format.fprintf fmt "loop_s%d" sid
+  | Bfct -> Format.fprintf fmt "fct"
+
+let pp_node_dot fmt { kind } =
+  match kind with
+  | Vstart  -> Format.fprintf fmt "START"
+  | Vend -> Format.fprintf fmt "END"
+  | Vexit -> Format.fprintf fmt "EXIT"
+  | VfctIn -> Format.fprintf fmt "FIN"
+  | VfctOut -> Format.fprintf fmt "FOUT"
+  | VblkIn (b,_) -> Format.fprintf fmt "IN_%a" pp_node_type_dot b
+  | VblkOut (b,_) -> Format.fprintf fmt "OUT_%a" pp_node_type_dot b
+  | Vstmt { sid } -> Format.fprintf fmt "STMT_s%d" sid
+  | Vloop(_,{ sid }) -> Format.fprintf fmt "LOOP_s%d" sid
+  | Vloop2(_,k) -> Format.fprintf fmt "LOOP2_%d" k
+  | Vtest(true,{ sid },_) -> Format.fprintf fmt "TEST_IN_s%d" sid
+  | Vtest(false,{ sid },_) -> Format.fprintf fmt "TEST_OUT_s%d" sid
+  | Vswitch({ sid },_) -> Format.fprintf fmt "SWITCH_s%d" sid
+  | Vcall({ sid },_,_,_) -> Format.fprintf fmt "CALL_s%d" sid
+
+let pp_cfg_dot name { kernel_function = kf ; graph } =
+  Command.pp_to_file
+    (Printf.sprintf "%s-%s.dot" (Kernel_function.get_name kf) name)
+    begin fun fmt ->
+      Format.fprintf fmt "digraph %s {@\n" name ;
+      Format.fprintf fmt "  rankdir = TB;@\n" ;
+      CFG.iter_edges_e
+        (fun (s,i,t) ->
+           match !i with
+           | Enext -> ()
+           | Enone ->
+               Format.fprintf fmt " %a -> %a ;@\n" pp_node_dot s pp_node_dot t
+           | info ->
+               Format.fprintf fmt " %a -> %a [ label=\"%a\" ] ;@\n"
+                 pp_node_dot s pp_node_dot t EL.pretty info
+        ) graph ;
+      Format.fprintf fmt "}@." ;
+    end
+*)
+
 let cfg_from_definition kf f =
   let kf_name = Kernel_function.get_name kf in
   let cfg, fct_in, fct_out = init_cfg false kf in
@@ -1273,6 +1367,8 @@ module KfCfg =
                   unreachables = [];
                   loop_nodes = None;
                   loop_cpt = 0;
+                  node_break = None;
+                  node_continue = None;
                 }
              )
              Kernel_function.reprs
diff --git a/src/plugins/wp/tests/wp/cfg_loop.i b/src/plugins/wp/tests/wp/cfg_loop.i
new file mode 100644
index 0000000000000000000000000000000000000000..7b92f76245961022f2ae2d52cef7c403b1949e8c
--- /dev/null
+++ b/src/plugins/wp/tests/wp/cfg_loop.i
@@ -0,0 +1,55 @@
+/* -------------------------------------------------------------------------- */
+/* --- Bugs related to CFG for loops & switch                             --- */
+/* -------------------------------------------------------------------------- */
+
+// All contract shall be provable
+
+void loop_switch(int *a,int c)
+{
+  *a = 1;
+  int b = 2;
+  /*@
+    loop invariant b == 2;
+    loop invariant *a ==1;
+    loop assigns b, *a;
+  */
+  while(1) {
+    switch (c) {
+    case 1:
+      *a = 1;
+      b = 2;
+      break;
+    case 2:
+      b = 2;
+      *a = 1;
+      break;
+    default:
+      *a =1;
+      b = 2;
+      break;
+    }
+  }
+}
+
+int a;
+
+void loop_continue(int x,int y)
+{
+  int *p = &a;
+  /*@
+    loop invariant p == \at(p, LoopEntry);
+    loop assigns *p, x;
+  */
+  while(1)
+    {
+      if(x)
+        {
+          if (y)
+            continue;
+          *p = 1;
+          x++;
+        }
+      else
+        return;
+    }
+}
diff --git a/src/plugins/wp/tests/wp/oracle/cfg_loop.res.oracle b/src/plugins/wp/tests/wp/oracle/cfg_loop.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..fde404cb14e6dbcb899b1df90bf9bc5c4e843a46
--- /dev/null
+++ b/src/plugins/wp/tests/wp/oracle/cfg_loop.res.oracle
@@ -0,0 +1,98 @@
+# frama-c -wp [...]
+[kernel] Parsing tests/wp/cfg_loop.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Loading driver 'share/wp.driver'
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Function loop_continue
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 40):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Establishment of Invariant (file tests/wp/cfg_loop.i, line 40):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Loop assigns (file tests/wp/cfg_loop.i, line 41):
+Prove: true.
+
+------------------------------------------------------------
+------------------------------------------------------------
+  Function loop_switch
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 12) (1/3):
+Tags: Default.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 12) (2/3):
+Tags: Case 2.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 12) (3/3):
+Tags: Case 1.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Establishment of Invariant (file tests/wp/cfg_loop.i, line 12):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 13) (1/3):
+Tags: Default.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 13) (2/3):
+Tags: Case 2.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Preservation of Invariant (file tests/wp/cfg_loop.i, line 13) (3/3):
+Tags: Case 1.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Establishment of Invariant (file tests/wp/cfg_loop.i, line 13):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Loop assigns (file tests/wp/cfg_loop.i, line 14) (1/4):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Loop assigns (file tests/wp/cfg_loop.i, line 14) (2/4):
+Effect at line 16
+Tags: Default.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Loop assigns (file tests/wp/cfg_loop.i, line 14) (3/4):
+Effect at line 16
+Tags: Case 2.
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Loop assigns (file tests/wp/cfg_loop.i, line 14) (4/4):
+Effect at line 16
+Tags: Case 1.
+Prove: true.
+
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp/oracle_qualif/cfg_loop.res.oracle b/src/plugins/wp/tests/wp/oracle_qualif/cfg_loop.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..783f051c009e91c40916a4857448372bc694ba58
--- /dev/null
+++ b/src/plugins/wp/tests/wp/oracle_qualif/cfg_loop.res.oracle
@@ -0,0 +1,28 @@
+# frama-c -wp [...]
+[kernel] Parsing tests/wp/cfg_loop.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Loading driver 'share/wp.driver'
+[wp] Warning: Missing RTE guards
+[wp] 15 goals scheduled
+[wp] [Qed] Goal typed_loop_continue_loop_invariant_preserved : Valid
+[wp] [Qed] Goal typed_loop_continue_loop_invariant_established : Valid
+[wp] [Qed] Goal typed_loop_continue_loop_assigns : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_preserved_part1 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_preserved_part2 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_preserved_part3 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_established : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_2_preserved_part1 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_2_preserved_part2 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_2_preserved_part3 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_invariant_2_established : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_assigns_part1 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_assigns_part2 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_assigns_part3 : Valid
+[wp] [Qed] Goal typed_loop_switch_loop_assigns_part4 : Valid
+[wp] Proved goals:   15 / 15
+  Qed:            15
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  loop_switch              12        -       12       100%
+  loop_continue             3        -        3       100%
+------------------------------------------------------------