[clang] make switch statement translation more robust

Summary:
Labels inside switch statements were causing havoc (see test), and the translation of switch statements in general could be improved to handle more cases.

It turns out that `case` (and `default`) statements are more or less fancy labels into the code. In other words, if you erase all the `case XXX:` and `default:` strings in the `switch` statement you get the real structure of the program, and `switch` just jumps straight to the first `case` directives (and to the second if the first one is not satisfied, etc. until all `case`/`default` have been considered).

This suggests an alternative implementation: translate the body of the `switch` and simply record the list of switch cases inside that body, along with where they point to. Then post-process this list to construct the control flow of the `switch`, which points into the control-flow of the `body`. In order not to modify every function in `CTrans` to propagate the current list of cases, I created an ugly `ref` inside `SwitchCase` instead (but it cannot be directly accessed and it's guaranteed to be well-parenthesised wrt nested switches by the `SwitchCase` API so it's not too bad).

[unrelated] Also make translation failures output more information about what exactly in the source code is causing the crash, and the ancestors in the AST that lead to the crash site.

Reviewed By: martinoluca

Differential Revision: D8011046

fbshipit-source-id: 8455090
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent 20de2f66ad
commit 8715c4f892

@ -28,13 +28,20 @@ let pp f (loc: t) =
if loc.col <> -1 then F.fprintf f ", column %d" loc.col
let to_string loc =
let s = string_of_int loc.line in
if loc.col <> -1 then Printf.sprintf "%s:%d" s loc.col else s
let pp_short f loc =
F.pp_print_int f loc.line ;
if loc.col <> -1 then F.fprintf f ":%d" loc.col
let to_string loc = F.asprintf "%a" pp_short loc
(** Pretty print a file-position of a location *)
let pp_file_pos f (loc: t) =
let fname = SourceFile.to_string loc.file in
let pos = to_string loc in
F.fprintf f "%s:%s" fname pos
let pp_file_pos f (loc: t) = F.fprintf f "%a:%a" SourceFile.pp loc.file pp_short loc
let pp_range f (loc_start, loc_end) =
let pp_end loc_start f loc_end =
if Int.equal loc_end.line loc_start.line then
if Int.equal loc_end.col loc_start.col then () else F.fprintf f "-%d" loc_end.col
else F.fprintf f "-%a" pp_short loc_end
in
F.fprintf f "%a%a" pp_file_pos loc_start (pp_end loc_start) loc_end

@ -32,3 +32,5 @@ val to_string : t -> string
val pp_file_pos : Format.formatter -> t -> unit
(** Pretty print a file-position of a location *)
val pp_range : Format.formatter -> t * t -> unit

@ -0,0 +1,39 @@
(*
* Copyright (c) 2018 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
module F = Format
type condition = Case of Clang_ast_t.stmt | Default
type t = {condition: condition; stmt_info: Clang_ast_t.stmt_info; root_nodes: Procdesc.Node.t list}
let current_cases : t list ref = ref []
let in_switch_body ~f x =
let outer_switch_cases = !current_cases in
current_cases := [] ;
let res = f x in
let rev_switch_cases = !current_cases in
current_cases := outer_switch_cases ;
(List.rev rev_switch_cases, res)
let add switch_case = current_cases := switch_case :: !current_cases
let pp_condition fmt = function
| Case stmt ->
F.fprintf fmt "case %a:" (Pp.to_string ~f:Clang_ast_j.string_of_stmt) stmt
| Default ->
F.pp_print_string fmt "default:"
let pp fmt {condition; root_nodes} =
F.fprintf fmt "%a -> @[<h>[%a]@]" pp_condition condition
(Pp.semicolon_seq Procdesc.Node.pp)
root_nodes

@ -0,0 +1,23 @@
(*
* Copyright (c) 2018 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
module F = Format
type condition = Case of Clang_ast_t.stmt | Default
type t = {condition: condition; stmt_info: Clang_ast_t.stmt_info; root_nodes: Procdesc.Node.t list}
val in_switch_body : f:('a -> 'b) -> 'a -> t list * 'b
val add : t -> unit
val pp_condition : F.formatter -> condition -> unit [@@warning "-32"]
val pp : F.formatter -> t -> unit [@@warning "-32"]

@ -747,14 +747,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let rec labelStmt_trans trans_state stmt_info stmt_list label_name =
let context = trans_state.context in
(* go ahead with the translation *)
let res_trans =
match stmt_list with
| [stmt] ->
instruction trans_state stmt
| _ ->
(* expected a stmt or at most a compoundstmt *) assert false
in
let[@warning "-8"] [stmt] = stmt_list in
let res_trans = instruction trans_state stmt in
(* create the label root node into the hashtbl *)
let sil_loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file stmt_info
@ -1523,7 +1517,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let prune_nodes' = if branch then prune_nodes_t else prune_nodes_f in
List.iter
~f:(fun n -> Procdesc.node_set_succs_exn context.procdesc n res_trans.control.root_nodes [])
prune_nodes'
prune_nodes' ;
res_trans
in
match stmt_list with
| [cond; exp1; exp2] ->
@ -1546,8 +1541,12 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(cond_trans ~if_kind:Sil.Ik_bexp ~negate_cond:false)
in
(* Note: by contruction prune nodes are leafs_nodes_cond *)
do_branch true exp1 var_typ res_trans_cond.control.leaf_nodes join_node pvar ;
do_branch false exp2 var_typ res_trans_cond.control.leaf_nodes join_node pvar ;
let _ : trans_result =
do_branch true exp1 var_typ res_trans_cond.control.leaf_nodes join_node pvar
in
let _ : trans_result =
do_branch false exp2 var_typ res_trans_cond.control.leaf_nodes join_node pvar
in
let id = Ident.create_fresh Ident.knormal in
let instrs = [Sil.Load (id, Exp.Lvar pvar, var_typ, sil_loc)] in
mk_trans_result (Exp.Var id, typ)
@ -1764,179 +1763,104 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
assert false
(* Assumption: the CompoundStmt can be made of different stmts, not just CaseStmts *)
and caseStmt_trans trans_state stmt_info case_stmt_list =
(* ignore the [case lhs ... rhs: body] form, only support the [case condition: body] form *)
let[@warning "-8"] [condition; _rhs; body] = case_stmt_list in
let body_trans_result = instruction trans_state body in
(let open SwitchCase in
add {condition= Case condition; stmt_info; root_nodes= body_trans_result.control.root_nodes}) ;
body_trans_result
and defaultStmt_trans trans_state stmt_info default_stmt_list =
let[@warning "-8"] [body] = default_stmt_list in
let body_trans_result = instruction trans_state body in
(let open SwitchCase in
add {condition= Default; stmt_info; root_nodes= body_trans_result.control.root_nodes}) ;
body_trans_result
and switchStmt_trans trans_state stmt_info switch_stmt_list =
(* overview: translate the body of the switch statement, which automatically collects the
various cases at the same time, then link up the cases together and together with the switch
condition variable *)
(* unsupported: initialization *)
let[@warning "-8"] [_initialization; variable; condition; body] = switch_stmt_list in
let context = trans_state.context in
let succ_nodes = trans_state.succ_nodes in
let continuation = trans_state.continuation in
let sil_loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file stmt_info
in
let open Clang_ast_t in
match switch_stmt_list with
| [_; decl_stmt; cond; CompoundStmt (stmt_info, stmt_list)] ->
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in
let trans_state' = {trans_state_pri with succ_nodes= []} in
let res_trans_cond_tmp = instruction trans_state' cond in
let switch_special_cond_node =
let node_kind = Procdesc.Node.Stmt_node "Switch_stmt" in
Procdesc.create_node context.procdesc sil_loc node_kind res_trans_cond_tmp.control.instrs
in
List.iter
~f:(fun n' ->
Procdesc.node_set_succs_exn context.procdesc n' [switch_special_cond_node] [] )
res_trans_cond_tmp.control.leaf_nodes ;
let root_nodes =
if res_trans_cond_tmp.control.root_nodes <> [] then res_trans_cond_tmp.control.root_nodes
else [switch_special_cond_node]
in
let switch_e_cond', _ = res_trans_cond_tmp.return in
let res_trans_cond =
{ res_trans_cond_tmp with
control=
{res_trans_cond_tmp.control with root_nodes; leaf_nodes= [switch_special_cond_node]}
}
in
let res_trans_decl = declStmt_in_condition_trans trans_state decl_stmt res_trans_cond in
let trans_state_no_pri =
if PriorityNode.own_priority_node trans_state_pri.priority stmt_info then
{trans_state_pri with priority= Free}
else trans_state_pri
in
let switch_exit_point = succ_nodes in
let continuation' =
match continuation with
| Some cont ->
Some {cont with break= switch_exit_point}
| None ->
Some {break= switch_exit_point; continue= []; return_temp= false}
in
let trans_state'' = {trans_state_no_pri with continuation= continuation'} in
let merge_into_cases stmt_list =
(* returns list_of_cases * before_any_case_instrs *)
let rec aux rev_stmt_list acc cases =
match rev_stmt_list with
| CaseStmt (info, a :: b :: CaseStmt x :: c) :: rest ->
(* case x: case y: ... *)
if c <> [] (* empty case with nested case, then followed by some instructions *)
then assert false ;
let rest' = CaseStmt (info, [a; b]) :: rest in
let rev_stmt_list' = CaseStmt x :: rest' in
aux rev_stmt_list' acc cases
| CaseStmt (info, a :: b :: DefaultStmt x :: c) :: rest ->
(* case x: default: ... *)
if c <> [] (* empty case with nested case, then followed by some instructions *)
then assert false ;
let rest' = CaseStmt (info, [a; b]) :: rest in
let rev_stmt_list' = DefaultStmt x :: rest' in
aux rev_stmt_list' acc cases
| DefaultStmt (info, CaseStmt x :: c) :: rest ->
(* default: case x: ... *)
if c <> [] (* empty case with nested case, then followed by some instructions *)
then assert false ;
let rest' = DefaultStmt (info, []) :: rest in
let rev_stmt_list' = CaseStmt x :: rest' in
aux rev_stmt_list' acc cases
| CaseStmt (info, a :: b :: c) :: rest ->
aux rest [] (CaseStmt (info, a :: b :: c @ acc) :: cases)
| DefaultStmt (info, c) :: rest ->
(* default is always the last in the list *)
aux rest [] (DefaultStmt (info, c @ acc) :: cases)
| x :: rest ->
aux rest (x :: acc) cases
| [] ->
(cases, acc)
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in
let trans_state' = {trans_state_pri with succ_nodes= []} in
let res_trans_cond_tmp = instruction trans_state' condition in
let switch_node =
let node_kind = Procdesc.Node.Stmt_node "SwitchStmt" in
Procdesc.create_node context.procdesc sil_loc node_kind res_trans_cond_tmp.control.instrs
in
List.iter
~f:(fun n' -> Procdesc.node_set_succs_exn context.procdesc n' [switch_node] [])
res_trans_cond_tmp.control.leaf_nodes ;
let root_nodes =
if res_trans_cond_tmp.control.root_nodes <> [] then res_trans_cond_tmp.control.root_nodes
else [switch_node]
in
let condition_exp, _ = res_trans_cond_tmp.return in
let condition_result =
{ res_trans_cond_tmp with
control= {res_trans_cond_tmp.control with root_nodes; leaf_nodes= [switch_node]} }
in
let variable_result = declStmt_in_condition_trans trans_state variable condition_result in
let trans_state_no_pri =
if PriorityNode.own_priority_node trans_state_pri.priority stmt_info then
{trans_state_pri with priority= Free}
else trans_state_pri
in
let continuation' =
let switch_exit_point = trans_state.succ_nodes in
match trans_state.continuation with
| Some cont ->
Some {cont with break= switch_exit_point}
| None ->
Some {break= switch_exit_point; continue= []; return_temp= false}
in
let inner_trans_state = {trans_state_no_pri with continuation= continuation'} in
let switch_cases, (_: trans_result) =
SwitchCase.in_switch_body ~f:(instruction inner_trans_state) body
in
let link_up_switch_cases curr_succ_nodes = function
| {SwitchCase.condition= Case case_condition; stmt_info; root_nodes} ->
(* create case prune nodes, link the then branch to [root_nodes], the else branch to
[curr_succ_nodes] *)
let trans_state_pri = PriorityNode.try_claim_priority_node inner_trans_state stmt_info in
let res_trans_case_const = instruction trans_state_pri case_condition in
let e_const, _ = res_trans_case_const.return in
let sil_eq_cond = Exp.BinOp (Binop.Eq, condition_exp, e_const) in
let sil_loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file stmt_info
in
aux (List.rev stmt_list) [] []
in
let list_of_cases, pre_case_stmts = merge_into_cases stmt_list in
let rec connected_instruction rev_instr_list successor_nodes =
(* returns the entry point of the translated set of instr *)
match rev_instr_list with
| [] ->
successor_nodes
| instr :: rest ->
let trans_state''' = {trans_state'' with succ_nodes= successor_nodes} in
let res_trans_instr = instruction trans_state''' instr in
let instr_entry_points = res_trans_instr.control.root_nodes in
connected_instruction rest instr_entry_points
in
let rec translate_and_connect_cases cases next_nodes next_prune_nodes =
let create_prune_nodes_for_case case =
match case with
| CaseStmt (stmt_info, case_const :: _ :: _) ->
let trans_state_pri =
PriorityNode.try_claim_priority_node trans_state'' stmt_info
in
let res_trans_case_const = instruction trans_state_pri case_const in
let e_const, _ = res_trans_case_const.return in
let sil_eq_cond = Exp.BinOp (Binop.Eq, switch_e_cond', e_const) in
let sil_loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file
stmt_info
in
let true_prune_node =
create_prune_node context.procdesc ~branch:true ~negate_cond:false sil_eq_cond
res_trans_case_const.control.instrs sil_loc Sil.Ik_switch
in
let false_prune_node =
create_prune_node context.procdesc ~branch:false ~negate_cond:true sil_eq_cond
res_trans_case_const.control.instrs sil_loc Sil.Ik_switch
in
(true_prune_node, false_prune_node)
| _ ->
assert false
let true_prune_node =
create_prune_node context.procdesc ~branch:true ~negate_cond:false sil_eq_cond
res_trans_case_const.control.instrs sil_loc Sil.Ik_switch
in
match cases with
(* top-down to handle default cases *)
| [] ->
(next_nodes, next_prune_nodes)
| (CaseStmt (_, _ :: _ :: case_content) as case) :: rest ->
let last_nodes, last_prune_nodes =
translate_and_connect_cases rest next_nodes next_prune_nodes
in
let case_entry_point = connected_instruction (List.rev case_content) last_nodes in
(* connects between cases, then continuation has priority about breaks *)
let prune_node_t, prune_node_f = create_prune_nodes_for_case case in
Procdesc.node_set_succs_exn context.procdesc prune_node_t case_entry_point [] ;
Procdesc.node_set_succs_exn context.procdesc prune_node_f last_prune_nodes [] ;
(case_entry_point, [prune_node_t; prune_node_f])
| DefaultStmt (stmt_info, default_content) :: rest ->
let sil_loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file
stmt_info
in
let placeholder_entry_point =
Procdesc.create_node context.procdesc sil_loc
(Procdesc.Node.Stmt_node "DefaultStmt_placeholder") []
in
let last_nodes, last_prune_nodes =
translate_and_connect_cases rest next_nodes [placeholder_entry_point]
in
let default_entry_point =
connected_instruction (List.rev default_content) last_nodes
in
Procdesc.node_set_succs_exn context.procdesc placeholder_entry_point
default_entry_point [] ;
(default_entry_point, last_prune_nodes)
| _ ->
assert false
in
let top_entry_point, top_prune_nodes =
translate_and_connect_cases list_of_cases succ_nodes succ_nodes
in
let _ = connected_instruction (List.rev pre_case_stmts) top_entry_point in
Procdesc.node_set_succs_exn context.procdesc switch_special_cond_node top_prune_nodes [] ;
let top_nodes = res_trans_decl.control.root_nodes in
(* succ_nodes will remove the temps *)
mk_trans_result (mk_fresh_void_exp_typ ())
{empty_control with root_nodes= top_nodes; leaf_nodes= succ_nodes}
| _ ->
(* TODO(t21762295) this raises sometimes *)
CFrontend_config.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range
"Unexpected Switch Statement sub-expression list: [%a]"
(Pp.semicolon_seq (Pp.to_string ~f:Clang_ast_j.string_of_stmt))
switch_stmt_list
let false_prune_node =
create_prune_node context.procdesc ~branch:false ~negate_cond:true sil_eq_cond
res_trans_case_const.control.instrs sil_loc Sil.Ik_switch
in
Procdesc.node_set_succs_exn context.procdesc true_prune_node root_nodes [] ;
Procdesc.node_set_succs_exn context.procdesc false_prune_node curr_succ_nodes [] ;
(* return prune nodes as next roots *)
[true_prune_node; false_prune_node]
| {SwitchCase.condition= Default; root_nodes} ->
(* just return the [root_nodes] to be linked to the previous case's fallthrough *)
root_nodes
in
let cases_root_nodes =
List.fold switch_cases ~init:trans_state.succ_nodes ~f:link_up_switch_cases
in
Procdesc.node_set_succs_exn context.procdesc switch_node cases_root_nodes [] ;
let top_nodes = variable_result.control.root_nodes in
mk_trans_result (mk_fresh_void_exp_typ ())
{empty_control with root_nodes= top_nodes; leaf_nodes= trans_state.succ_nodes}
and stmtExpr_trans trans_state source_range stmt_list =
@ -3213,7 +3137,24 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
"Translating statement '%a' (pointer= '%a')@\n@[<hv2>"
(Pp.to_string ~f:Clang_ast_proj.get_stmt_kind_string)
instr pp_pointer instr ;
let trans_result = instruction_aux trans_state instr in
let trans_result =
try instruction_aux trans_state instr with e ->
IExn.reraise_after e ~f:(fun () ->
let {Clang_ast_t.si_source_range}, _ = Clang_ast_proj.get_stmt_tuple instr in
let source_file =
trans_state.context.CContext.translation_unit_context.CFrontend_config.source_file
in
let loc_start =
CLocation.location_of_source_range ~pick_location:`Start source_file si_source_range
in
let loc_end =
CLocation.location_of_source_range ~pick_location:`End source_file si_source_range
in
L.internal_error "%a: ERROR translating statement '%a'@\n" Location.pp_range
(loc_start, loc_end)
(Pp.to_string ~f:Clang_ast_proj.get_stmt_kind_string)
instr )
in
L.(debug Capture Verbose) "@]" ;
trans_result
@ -3253,12 +3194,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
ifStmt_trans trans_state stmt_info stmt_list
| SwitchStmt (stmt_info, switch_stmt_list) ->
switchStmt_trans trans_state stmt_info switch_stmt_list
| CaseStmt ({Clang_ast_t.si_source_range}, _) ->
(* where do we even get case stmts outside of the switch stmt? (t21762295) *)
CFrontend_config.incorrect_assumption __POS__ si_source_range
"Case statement outside of switch statement: %a"
(Pp.to_string ~f:Clang_ast_j.string_of_stmt)
instr
| CaseStmt (stmt_info, stmt_list) ->
caseStmt_trans trans_state stmt_info stmt_list
| DefaultStmt (stmt_info, stmt_list) ->
defaultStmt_trans trans_state stmt_info stmt_list
| StmtExpr ({Clang_ast_t.si_source_range}, stmt_list, _) ->
stmtExpr_trans trans_state si_source_range stmt_list
| ForStmt (stmt_info, [init; decl_stmt; condition; increment; body]) ->
@ -3543,8 +3482,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| SEHFinallyStmt _
| SEHLeaveStmt _
| SEHTryStmt _
| ShuffleVectorExpr _
| DefaultStmt _ ->
| ShuffleVectorExpr _ ->
let (stmt_info, stmts), ret_typ =
match Clang_ast_proj.get_expr_tuple instr with
| Some (stmt_info, stmts, expr_info) ->

@ -15,7 +15,7 @@ type continuation =
{ break: Procdesc.Node.t list
; continue: Procdesc.Node.t list
; return_temp: bool
(* true if temps should not be removed in the node but returned to ancestors *) }
(** true if temps should not be removed in the node but returned to ancestors *) }
type priority_node = Free | Busy of Clang_ast_t.pointer

@ -9,10 +9,13 @@
#import <stdio.h>
int m1() {
int test_switch1() {
int value = 0;
// infinite loop
while (value < 10) {
switch (value) {
// code before the first case statement gets skipped but can be used to
// declare variables
int x = 1;
printf("(out)HELLO WORLD!");
x = value + 1;
@ -32,12 +35,10 @@ int m1() {
return 0;
}
int m2() {
int test_switch2() {
int value = 0;
switch (value) {
int x = 1;
printf("(out)HELLO WORLD!");
x = value + 1;
int x;
case 0:
printf("(0)HELLO WORLD!");
break;
@ -57,7 +58,7 @@ int m2() {
return 0;
}
int m3() {
int test_switch3() {
int value = 0;
switch (value) {
case 0:
@ -75,12 +76,10 @@ int m3() {
return 0;
}
int m4() {
int test_switch4() {
int value = 0;
switch (value) {
int x = 1;
printf("(out)HELLO WORLD!");
x = value + 1;
int x;
case 0:
printf("(0)HELLO WORLD!");
break;
@ -100,11 +99,11 @@ int m4() {
return 0;
}
int m5() {
int test_switch5() {
int value = 0;
while (value < 10) {
switch (value) {
int x = 1;
int x;
printf("(out)HELLO WORLD!");
x = value + 1;
continue;
@ -116,7 +115,7 @@ int m5() {
return 0;
}
int m6() {
int test_switch6() {
int value = 0;
switch (value > 0 ? 1 : 0) {
case 0:
@ -136,7 +135,7 @@ int m6() {
int getValue() { return 1; }
int m7() {
int test_switch7() {
int value = 0;
switch (getValue()) {
case 0:
@ -154,7 +153,7 @@ int m7() {
return 0;
}
int m8() {
int test_switch8() {
int value = 0;
while (value < 10) {
switch (getValue() == 0 ? 1 : 2) {
@ -176,19 +175,19 @@ int m8() {
return 0;
}
int m9() {
int test_switch9() {
int value = 0;
switch (value) {}
return 0;
}
int m10() {
int test_switch10() {
int value = 0;
switch (value = 7) {}
return 0;
}
int m11() {
int test_switch11() {
int value = 0;
switch (value = (value == 0 ? 7 : 9)) {
case 0:

@ -0,0 +1,27 @@
/*
* Copyright (c) 2018 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
int unroll_loop(int n) {
int ret = 0;
int loop = n + 3 / 4;
switch (n % 8) {
case 0:
do {
ret++;
case 3:
ret++;
if (1) {
case 2:
ret++;
}
case 1:
ret++;
} while (--loop > 0);
}
return ret;
}

@ -0,0 +1,108 @@
/* @generated */
digraph cfg {
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_1" [label="1: Start unroll_loop\nFormals: n:int\nLocals: loop:int ret:int \n DECLARE_LOCALS(&return,&loop,&ret); [line 9, column 1]\n " color=yellow style=filled]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_1" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_25" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_2" [label="2: Exit unroll_loop \n " color=yellow style=filled]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_3" [label="3: Return Stmt \n n$0=*&ret:int [line 26, column 10]\n *&return:int=n$0 [line 26, column 3]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_3" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_2" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_4" [label="4: SwitchStmt \n n$1=*&n:int [line 12, column 11]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_4" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_22" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_4" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_23" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_5" [label="5: + \n " ]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_5" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_15" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_6" [label="6: BinaryOperatorStmt: GT \n n$2=*&loop:int [line 24, column 16]\n *&loop:int=(n$2 - 1) [line 24, column 16]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_6" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_7" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_6" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_8" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_7" [label="7: Prune (true branch, do while) \n PRUNE(((n$2 - 1) > 0), true); [line 24, column 16]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_7" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_5" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_8" [label="8: Prune (false branch, do while) \n PRUNE(!((n$2 - 1) > 0), false); [line 24, column 16]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_8" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_3" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_9" [label="9: UnaryOperator \n n$3=*&ret:int [line 23, column 11]\n *&ret:int=(n$3 + 1) [line 23, column 11]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_9" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_6" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_10" [label="10: + \n " ]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_10" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_9" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_11" [label="11: Prune (true branch, if) \n PRUNE(1, true); [line 18, column 15]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_11" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_13" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_12" [label="12: Prune (false branch, if) \n PRUNE(!1, false); [line 18, column 15]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_12" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_10" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_13" [label="13: UnaryOperator \n n$4=*&ret:int [line 20, column 15]\n *&ret:int=(n$4 + 1) [line 20, column 15]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_13" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_10" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_14" [label="14: UnaryOperator \n n$7=*&ret:int [line 17, column 11]\n *&ret:int=(n$7 + 1) [line 17, column 11]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_14" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_11" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_14" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_12" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_15" [label="15: UnaryOperator \n n$8=*&ret:int [line 15, column 9]\n *&ret:int=(n$8 + 1) [line 15, column 9]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_15" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_14" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_16" [label="16: Prune (true branch, switch) \n PRUNE(((n$1 % 8) == 1), true); [line 22, column 9]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_16" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_9" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_17" [label="17: Prune (false branch, switch) \n PRUNE(!((n$1 % 8) == 1), false); [line 22, column 9]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_17" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_3" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_18" [label="18: Prune (true branch, switch) \n PRUNE(((n$1 % 8) == 2), true); [line 19, column 13]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_18" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_13" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_19" [label="19: Prune (false branch, switch) \n PRUNE(!((n$1 % 8) == 2), false); [line 19, column 13]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_19" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_16" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_19" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_17" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_20" [label="20: Prune (true branch, switch) \n PRUNE(((n$1 % 8) == 3), true); [line 16, column 9]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_20" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_14" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_21" [label="21: Prune (false branch, switch) \n PRUNE(!((n$1 % 8) == 3), false); [line 16, column 9]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_21" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_18" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_21" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_19" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_22" [label="22: Prune (true branch, switch) \n PRUNE(((n$1 % 8) == 0), true); [line 13, column 5]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_22" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_5" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_23" [label="23: Prune (false branch, switch) \n PRUNE(!((n$1 % 8) == 0), false); [line 13, column 5]\n " shape="invhouse"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_23" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_20" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_23" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_21" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_24" [label="24: DeclStmt \n n$11=*&n:int [line 11, column 14]\n *&loop:int=(n$11 + (3 / 4)) [line 11, column 3]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_24" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_4" ;
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_25" [label="25: DeclStmt \n *&ret:int=0 [line 10, column 3]\n " shape="box"]
"unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_25" -> "unroll_loop.7d9e50ecf5e5106a8dd5deee005639d6_24" ;
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2018 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
int label_default(char x) {
int ret = 0;
switch (x) {
case 1:
ret++;
goto l;
case 2:
ret = 2;
break;
l:
default:
ret--;
}
return ret;
}
int label_case(char x) {
int ret = 0;
switch (x) {
case 1:
ret++;
goto l;
l:
case 2:
case 3:
ret++;
break;
}
return ret;
}

@ -0,0 +1,114 @@
/* @generated */
digraph cfg {
"label_case.83d07a314df100648248d9156212096b_1" [label="1: Start label_case\nFormals: x:char\nLocals: ret:int \n DECLARE_LOCALS(&return,&ret); [line 26, column 1]\n " color=yellow style=filled]
"label_case.83d07a314df100648248d9156212096b_1" -> "label_case.83d07a314df100648248d9156212096b_14" ;
"label_case.83d07a314df100648248d9156212096b_2" [label="2: Exit label_case \n " color=yellow style=filled]
"label_case.83d07a314df100648248d9156212096b_3" [label="3: Return Stmt \n n$0=*&ret:int [line 38, column 10]\n *&return:int=n$0 [line 38, column 3]\n " shape="box"]
"label_case.83d07a314df100648248d9156212096b_3" -> "label_case.83d07a314df100648248d9156212096b_2" ;
"label_case.83d07a314df100648248d9156212096b_4" [label="4: SwitchStmt \n n$1=*&x:char [line 28, column 11]\n " shape="box"]
"label_case.83d07a314df100648248d9156212096b_4" -> "label_case.83d07a314df100648248d9156212096b_12" ;
"label_case.83d07a314df100648248d9156212096b_4" -> "label_case.83d07a314df100648248d9156212096b_13" ;
"label_case.83d07a314df100648248d9156212096b_5" [label="5: UnaryOperator \n n$3=*&ret:int [line 35, column 7]\n *&ret:int=(n$3 + 1) [line 35, column 7]\n " shape="box"]
"label_case.83d07a314df100648248d9156212096b_5" -> "label_case.83d07a314df100648248d9156212096b_3" ;
"label_case.83d07a314df100648248d9156212096b_6" [label="6: Skip GotoLabel_l \n " color="gray"]
"label_case.83d07a314df100648248d9156212096b_6" -> "label_case.83d07a314df100648248d9156212096b_5" ;
"label_case.83d07a314df100648248d9156212096b_7" [label="7: UnaryOperator \n n$6=*&ret:int [line 30, column 7]\n *&ret:int=(n$6 + 1) [line 30, column 7]\n " shape="box"]
"label_case.83d07a314df100648248d9156212096b_7" -> "label_case.83d07a314df100648248d9156212096b_6" ;
"label_case.83d07a314df100648248d9156212096b_8" [label="8: Prune (true branch, switch) \n PRUNE((n$1 == 3), true); [line 34, column 5]\n " shape="invhouse"]
"label_case.83d07a314df100648248d9156212096b_8" -> "label_case.83d07a314df100648248d9156212096b_5" ;
"label_case.83d07a314df100648248d9156212096b_9" [label="9: Prune (false branch, switch) \n PRUNE(!(n$1 == 3), false); [line 34, column 5]\n " shape="invhouse"]
"label_case.83d07a314df100648248d9156212096b_9" -> "label_case.83d07a314df100648248d9156212096b_3" ;
"label_case.83d07a314df100648248d9156212096b_10" [label="10: Prune (true branch, switch) \n PRUNE((n$1 == 2), true); [line 33, column 5]\n " shape="invhouse"]
"label_case.83d07a314df100648248d9156212096b_10" -> "label_case.83d07a314df100648248d9156212096b_5" ;
"label_case.83d07a314df100648248d9156212096b_11" [label="11: Prune (false branch, switch) \n PRUNE(!(n$1 == 2), false); [line 33, column 5]\n " shape="invhouse"]
"label_case.83d07a314df100648248d9156212096b_11" -> "label_case.83d07a314df100648248d9156212096b_8" ;
"label_case.83d07a314df100648248d9156212096b_11" -> "label_case.83d07a314df100648248d9156212096b_9" ;
"label_case.83d07a314df100648248d9156212096b_12" [label="12: Prune (true branch, switch) \n PRUNE((n$1 == 1), true); [line 29, column 5]\n " shape="invhouse"]
"label_case.83d07a314df100648248d9156212096b_12" -> "label_case.83d07a314df100648248d9156212096b_7" ;
"label_case.83d07a314df100648248d9156212096b_13" [label="13: Prune (false branch, switch) \n PRUNE(!(n$1 == 1), false); [line 29, column 5]\n " shape="invhouse"]
"label_case.83d07a314df100648248d9156212096b_13" -> "label_case.83d07a314df100648248d9156212096b_10" ;
"label_case.83d07a314df100648248d9156212096b_13" -> "label_case.83d07a314df100648248d9156212096b_11" ;
"label_case.83d07a314df100648248d9156212096b_14" [label="14: DeclStmt \n *&ret:int=0 [line 27, column 3]\n " shape="box"]
"label_case.83d07a314df100648248d9156212096b_14" -> "label_case.83d07a314df100648248d9156212096b_4" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_1" [label="1: Start label_default\nFormals: x:char\nLocals: ret:int \n DECLARE_LOCALS(&return,&ret); [line 10, column 1]\n " color=yellow style=filled]
"label_default.f30729864b0243c0a794ef0254fe7d23_1" -> "label_default.f30729864b0243c0a794ef0254fe7d23_13" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_2" [label="2: Exit label_default \n " color=yellow style=filled]
"label_default.f30729864b0243c0a794ef0254fe7d23_3" [label="3: Return Stmt \n n$0=*&ret:int [line 23, column 10]\n *&return:int=n$0 [line 23, column 3]\n " shape="box"]
"label_default.f30729864b0243c0a794ef0254fe7d23_3" -> "label_default.f30729864b0243c0a794ef0254fe7d23_2" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_4" [label="4: SwitchStmt \n n$1=*&x:char [line 12, column 11]\n " shape="box"]
"label_default.f30729864b0243c0a794ef0254fe7d23_4" -> "label_default.f30729864b0243c0a794ef0254fe7d23_11" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_4" -> "label_default.f30729864b0243c0a794ef0254fe7d23_12" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_5" [label="5: UnaryOperator \n n$2=*&ret:int [line 21, column 7]\n *&ret:int=(n$2 - 1) [line 21, column 7]\n " shape="box"]
"label_default.f30729864b0243c0a794ef0254fe7d23_5" -> "label_default.f30729864b0243c0a794ef0254fe7d23_3" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_6" [label="6: Skip GotoLabel_l \n " color="gray"]
"label_default.f30729864b0243c0a794ef0254fe7d23_6" -> "label_default.f30729864b0243c0a794ef0254fe7d23_5" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_7" [label="7: BinaryOperatorStmt: Assign \n *&ret:int=2 [line 17, column 7]\n " shape="box"]
"label_default.f30729864b0243c0a794ef0254fe7d23_7" -> "label_default.f30729864b0243c0a794ef0254fe7d23_3" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_8" [label="8: UnaryOperator \n n$6=*&ret:int [line 14, column 7]\n *&ret:int=(n$6 + 1) [line 14, column 7]\n " shape="box"]
"label_default.f30729864b0243c0a794ef0254fe7d23_8" -> "label_default.f30729864b0243c0a794ef0254fe7d23_6" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_9" [label="9: Prune (true branch, switch) \n PRUNE((n$1 == 2), true); [line 16, column 5]\n " shape="invhouse"]
"label_default.f30729864b0243c0a794ef0254fe7d23_9" -> "label_default.f30729864b0243c0a794ef0254fe7d23_7" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_10" [label="10: Prune (false branch, switch) \n PRUNE(!(n$1 == 2), false); [line 16, column 5]\n " shape="invhouse"]
"label_default.f30729864b0243c0a794ef0254fe7d23_10" -> "label_default.f30729864b0243c0a794ef0254fe7d23_5" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_11" [label="11: Prune (true branch, switch) \n PRUNE((n$1 == 1), true); [line 13, column 5]\n " shape="invhouse"]
"label_default.f30729864b0243c0a794ef0254fe7d23_11" -> "label_default.f30729864b0243c0a794ef0254fe7d23_8" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_12" [label="12: Prune (false branch, switch) \n PRUNE(!(n$1 == 1), false); [line 13, column 5]\n " shape="invhouse"]
"label_default.f30729864b0243c0a794ef0254fe7d23_12" -> "label_default.f30729864b0243c0a794ef0254fe7d23_9" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_12" -> "label_default.f30729864b0243c0a794ef0254fe7d23_10" ;
"label_default.f30729864b0243c0a794ef0254fe7d23_13" [label="13: DeclStmt \n *&ret:int=0 [line 11, column 3]\n " shape="box"]
"label_default.f30729864b0243c0a794ef0254fe7d23_13" -> "label_default.f30729864b0243c0a794ef0254fe7d23_4" ;
}

@ -22,12 +22,12 @@ digraph cfg {
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_3" -> "switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_2" ;
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_4" [label="4: Switch_stmt \n n$2=*&n:int [line 14, column 11]\n " shape="box"]
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_4" [label="4: SwitchStmt \n n$2=*&n:int [line 14, column 11]\n " shape="box"]
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_4" -> "switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_12" ;
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_4" -> "switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_13" ;
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_5" [label="5: BinaryOperatorStmt: Assign \n n$5=_fun_h() [line 21, column 13]\n *&res:int=n$5 [line 21, column 7]\n " shape="box"]
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_5" [label="5: BinaryOperatorStmt: Assign \n n$6=_fun_h() [line 21, column 13]\n *&res:int=n$6 [line 21, column 7]\n " shape="box"]
"switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_5" -> "switch_with_fallthrough#6355028676793350740.9380c19327ea36a0a69b7e115d031492_3" ;

@ -234,66 +234,66 @@ digraph cfg {
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_4" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_3" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_5" [label="5: Switch_stmt \n n$6=*&n:int [line 117, column 11]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_5" [label="5: SwitchStmt \n n$6=*&n:int [line 117, column 11]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_5" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_17" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_5" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_18" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_6" [label="6: Destruction \n _=*&x4:break_scope::X [line 127, column 5]\n n$8=_fun_break_scope::X_~X(&x4:break_scope::X*) [line 127, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_6" [label="6: Destruction \n _=*&x4:break_scope::X [line 127, column 5]\n n$9=_fun_break_scope::X_~X(&x4:break_scope::X*) [line 127, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_6" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_4" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_7" [label="7: DeclStmt \n n$10=_fun_break_scope::X_X(&x4:break_scope::X*) [line 126, column 9]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_7" [label="7: DeclStmt \n n$11=_fun_break_scope::X_X(&x4:break_scope::X*) [line 126, column 9]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_7" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_6" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_8" [label="8: Prune (true branch, switch) \n PRUNE((n$6 == 3), true); [line 125, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_8" [label="8: Destruction \n _=*&x3:break_scope::X [line 124, column 5]\n n$13=_fun_break_scope::X_~X(&x3:break_scope::X*) [line 124, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_8" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_7" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_9" [label="9: Prune (false branch, switch) \n PRUNE(!(n$6 == 3), false); [line 125, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_9" [label="9: Destruction \n _=*&x3:break_scope::X [line 123, column 7]\n n$16=_fun_break_scope::X_~X(&x3:break_scope::X*) [line 123, column 7]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_9" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_4" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_10" [label="10: Destruction \n _=*&x3:break_scope::X [line 124, column 5]\n n$12=_fun_break_scope::X_~X(&x3:break_scope::X*) [line 124, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_10" [label="10: DeclStmt \n n$18=_fun_break_scope::X_X(&x3:break_scope::X*) [line 122, column 9]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_10" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_7" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_11" [label="11: Destruction \n _=*&x3:break_scope::X [line 123, column 7]\n n$15=_fun_break_scope::X_~X(&x3:break_scope::X*) [line 123, column 7]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_10" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_9" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_11" [label="11: Destruction \n _=*&x2:break_scope::X [line 120, column 5]\n n$20=_fun_break_scope::X_~X(&x2:break_scope::X*) [line 120, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_11" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_4" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_12" [label="12: DeclStmt \n n$17=_fun_break_scope::X_X(&x3:break_scope::X*) [line 122, column 9]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_11" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_10" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_12" [label="12: DeclStmt \n n$22=_fun_break_scope::X_X(&x2:break_scope::X*) [line 119, column 9]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_12" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_11" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_13" [label="13: Prune (true branch, switch) \n PRUNE((n$6 == 2), true); [line 121, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_13" [label="13: Prune (true branch, switch) \n PRUNE((n$6 == 3), true); [line 125, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_13" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_12" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" [label="14: Prune (false branch, switch) \n PRUNE(!(n$6 == 2), false); [line 121, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_13" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_7" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" [label="14: Prune (false branch, switch) \n PRUNE(!(n$6 == 3), false); [line 125, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_8" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_9" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_15" [label="15: Destruction \n _=*&x2:break_scope::X [line 120, column 5]\n n$19=_fun_break_scope::X_~X(&x2:break_scope::X*) [line 120, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_4" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_15" [label="15: Prune (true branch, switch) \n PRUNE((n$6 == 2), true); [line 121, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_15" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_12" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" [label="16: DeclStmt \n n$21=_fun_break_scope::X_X(&x2:break_scope::X*) [line 119, column 9]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_15" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_10" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" [label="16: Prune (false branch, switch) \n PRUNE(!(n$6 == 2), false); [line 121, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_15" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_13" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_17" [label="17: Prune (true branch, switch) \n PRUNE((n$6 == 1), true); [line 118, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_17" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_17" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_12" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_18" [label="18: Prune (false branch, switch) \n PRUNE(!(n$6 == 1), false); [line 118, column 5]\n " shape="invhouse"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_18" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_13" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_18" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_14" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_19" [label="19: DeclStmt \n n$23=_fun_break_scope::X_X(&x1:break_scope::X*) [line 116, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_18" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_15" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_18" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_16" ;
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_19" [label="19: DeclStmt \n n$24=_fun_break_scope::X_X(&x1:break_scope::X*) [line 116, column 5]\n " shape="box"]
"test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_19" -> "test_switch#break_scope#5012999682930893305.43ca855443a5fa68fa701447a90f7a1f_5" ;

@ -7,55 +7,51 @@ digraph cfg {
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_2" [label="2: Exit get \n " color=yellow style=filled]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_3" [label="3: Switch_stmt \n n$1=*&x:int [line 11, column 15]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_3" [label="3: SwitchStmt \n n$1=*&x:int [line 11, column 15]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_3" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_3" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_13" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_3" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_14" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_4" [label="4: DeclStmt \n n$2=*&a:int [line 11, column 19]\n *&x:int=n$2 [line 11, column 11]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_4" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_3" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_5" [label="5: DefaultStmt_placeholder \n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_5" [label="5: Return Stmt \n n$4=*&x:int [line 18, column 14]\n *&return:int=n$4 [line 18, column 7]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_5" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_6" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_6" [label="6: Return Stmt \n n$3=*&x:int [line 18, column 14]\n *&return:int=n$3 [line 18, column 7]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_5" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_2" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_6" [label="6: Return Stmt \n *&return:int=1 [line 16, column 7]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_6" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_2" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_7" [label="7: Return Stmt \n *&return:int=1 [line 16, column 7]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_7" [label="7: Return Stmt \n *&return:int=0 [line 14, column 7]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_7" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_2" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_8" [label="8: Prune (true branch, switch) \n PRUNE((n$1 == 2), true); [line 15, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_8" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_7" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_8" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_6" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_9" [label="9: Prune (false branch, switch) \n PRUNE(!(n$1 == 2), false); [line 15, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_9" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_5" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_10" [label="10: Return Stmt \n *&return:int=0 [line 14, column 7]\n " shape="box"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_10" [label="10: Prune (true branch, switch) \n PRUNE((n$1 == 1), true); [line 13, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_10" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_2" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" [label="11: Prune (true branch, switch) \n PRUNE((n$1 == 1), true); [line 13, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_10" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_7" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" [label="11: Prune (false branch, switch) \n PRUNE(!(n$1 == 1), false); [line 13, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_10" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" [label="12: Prune (false branch, switch) \n PRUNE(!(n$1 == 1), false); [line 13, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_8" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_9" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" [label="12: Prune (true branch, switch) \n PRUNE((n$1 == 0), true); [line 12, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_8" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_9" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_13" [label="13: Prune (true branch, switch) \n PRUNE((n$1 == 0), true); [line 12, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_7" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_13" [label="13: Prune (false branch, switch) \n PRUNE(!(n$1 == 0), false); [line 12, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_13" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_10" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_14" [label="14: Prune (false branch, switch) \n PRUNE(!(n$1 == 0), false); [line 12, column 5]\n " shape="invhouse"]
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_14" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_14" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_12" ;
"get#10177141129833125794.403aae26476e3a02c544075e122228e0_13" -> "get#10177141129833125794.403aae26476e3a02c544075e122228e0_11" ;
}

Loading…
Cancel
Save