diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 4511753e9..9f56731a9 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -987,6 +987,25 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s mk_trans_result (array_exp, typ) control + and struct_copy tenv loc e1 e2 typ struct_name = + let rec struct_copy_helper e1 e2 typ struct_name rev_acc = + let {Struct.fields} = Option.value_exn (Tenv.lookup tenv struct_name) in + List.fold fields ~init:rev_acc ~f:(fun rev_acc (field_name, field_typ, _) -> + let mk_field e = Exp.Lfield (e, field_name, typ) in + let e1 = mk_field e1 in + let e2 = mk_field e2 in + match field_typ.Typ.desc with + | Tstruct (CStruct _ as struct_name) -> + struct_copy_helper e1 e2 field_typ struct_name rev_acc + | _ -> + let id = Ident.create_fresh Ident.knormal in + Sil.Store {e1; root_typ= field_typ; typ= field_typ; e2= Exp.Var id; loc} + :: Sil.Load {id; e= e2; root_typ= field_typ; typ= field_typ; loc} + :: rev_acc ) + in + if Exp.equal e1 e2 then [] else struct_copy_helper e1 e2 typ struct_name [] |> List.rev + + and binaryOperator_trans trans_state binary_operator_info stmt_info expr_info stmt_list = L.debug Capture Verbose " BinaryOperator '%a' " (Pp.of_string ~f:Clang_ast_j.string_of_binary_operator_kind) @@ -1003,8 +1022,21 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let res_typ = CType_decl.qual_type_to_sil_type context.CContext.tenv expr_info.Clang_ast_t.ei_qual_type in - match stmt_list with - | [s1; s2] -> + match (stmt_list, res_typ.desc, binary_operator_info.Clang_ast_t.boi_kind) with + | ( [s1; Clang_ast_t.ImplicitCastExpr (_, [s2], _, _)] + , Tstruct (CStruct _ as struct_name) + , `Assign ) -> + let res_trans_e1, res_trans_e2 = + (instruction trans_state' s1, instruction trans_state' s2) + in + let instrs = + struct_copy context.CContext.tenv sil_loc (fst res_trans_e1.return) + (fst res_trans_e2.return) res_typ struct_name + in + [res_trans_e1.control; res_trans_e2.control; {empty_control with instrs}] + |> PriorityNode.compute_controls_to_parent trans_state_pri sil_loc node_name stmt_info + |> mk_trans_result res_trans_e1.return + | [s1; s2], _, _ -> (* Assumption: We expect precisely 2 stmt corresponding to the 2 operands*) (* NOTE: we create a node only if required. In that case this node *) (* becomes the successor of the nodes that may be created when *) @@ -1061,7 +1093,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s PriorityNode.compute_controls_to_parent trans_state_pri sil_loc node_name stmt_info all_res_trans |> mk_trans_result return - | _ -> + | _, _, _ -> (* Binary operator should have two operands *) assert false @@ -2512,7 +2544,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s and init_expr_trans_aux trans_state var_exp_typ var_stmt_info init_expr = (* For init expr, translate how to compute it and assign to the var *) - let var_exp, _var_typ = var_exp_typ in + let var_exp, var_typ = var_exp_typ in + let cstruct_name_opt = + match var_typ.Typ.desc with + | Tstruct (CStruct _ as struct_name) -> + Some struct_name + | _ -> + None + in let context = trans_state.context in let sil_loc = CLocation.location_of_stmt_info context.translation_unit_context.source_file var_stmt_info @@ -2523,6 +2562,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let res_trans_ie = let trans_state' = {trans_state_pri with succ_nodes= []; var_exp_typ= Some var_exp_typ} in let instruction' = exec_with_glvalue_as_reference instruction in + let init_expr = + match init_expr with + | Clang_ast_t.ImplicitCastExpr (_, [init_expr], _, _) when Option.is_some cstruct_name_opt + -> + init_expr + | _ -> + init_expr + in exec_with_block_priority_exception instruction' trans_state' init_expr var_stmt_info in L.debug Capture Verbose "init expr result: %a@\n" pp_control res_trans_ie.control ; @@ -2544,10 +2591,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let sil_e1', ie_typ = res_trans_ie.return in L.debug Capture Verbose "Sub-expr did not initialize %a, initializing with %a@\n" Exp.pp var_exp Exp.pp sil_e1' ; - Some - { empty_control with - instrs= - [Sil.Store {e1= var_exp; root_typ= ie_typ; typ= ie_typ; e2= sil_e1'; loc= sil_loc}] } + let instrs = + match cstruct_name_opt with + | Some struct_name -> + struct_copy context.CContext.tenv sil_loc var_exp sil_e1' var_typ struct_name + | None -> + [Sil.Store {e1= var_exp; root_typ= ie_typ; typ= ie_typ; e2= sil_e1'; loc= sil_loc}] + in + Some {empty_control with instrs} in let all_res_trans = res_trans_ie.control :: Option.to_list assign_trans_control_opt in L.debug Capture Verbose "sending init_expr_trans results to parent@\n" ; @@ -2876,72 +2927,77 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s ~exn:[] ; ret_node in - match stmt_list with - | [stmt] -> - (* return exp; *) - let ret_type = Procdesc.get_ret_type procdesc in - let ret_exp, ret_typ, var_control = - match context.CContext.return_param_typ with - | Some ret_param_typ -> - let name = CFrontend_config.return_param in - let pvar = Pvar.mk (Mangled.from_string name) procname in - let id = Ident.create_fresh Ident.knormal in - let instr = - Sil.Load - {id; e= Exp.Lvar pvar; root_typ= ret_param_typ; typ= ret_param_typ; loc= sil_loc} - in - let ret_typ = - match ret_param_typ.desc with Typ.Tptr (t, _) -> t | _ -> assert false - in - (Exp.Var id, ret_typ, Some {empty_control with instrs= [instr]}) - | None -> - (Exp.Lvar (Procdesc.get_ret_var procdesc), ret_type, None) - in - let trans_state' = - {trans_state_pri with succ_nodes= []; var_exp_typ= Some (ret_exp, ret_typ)} - in - L.debug Capture Verbose "Evaluating sub-expr of return@\n" ; - let res_trans_stmt = instruction trans_state' stmt in - L.debug Capture Verbose "Done evaluating sub-expr of return@\n" ; - let controls = - let var_control = - Option.map var_control ~f:(fun control -> - (* force node creation to place the load instruction [var_control] before the - translation of the sub-expr *) - let trans_state = - PriorityNode.force_claim_priority_node trans_state_pri stmt_info - in - PriorityNode.compute_control_to_parent trans_state sil_loc ReturnStmt stmt_info - control ) - in - PriorityNode.compute_controls_to_parent trans_state' sil_loc ReturnStmt stmt_info - (Option.to_list var_control @ [res_trans_stmt.control]) - in - let ret_instrs = - if List.exists ~f:(Exp.equal ret_exp) res_trans_stmt.control.initd_exps then [] - else - let sil_expr, _ = res_trans_stmt.return in - [Sil.Store {e1= ret_exp; root_typ= ret_type; typ= ret_typ; e2= sil_expr; loc= sil_loc}] - in - let ret_node = mk_ret_node ret_instrs in - L.debug Capture Verbose "Created return node %a with instrs [%a]@\n" Procdesc.Node.pp - ret_node - (Pp.seq ~sep:";" (Sil.pp_instr ~print_types:false Pp.text)) - ret_instrs ; - assert (List.is_empty controls.instrs) ; - List.iter controls.leaf_nodes ~f:(fun leaf -> - Procdesc.set_succs leaf ~normal:(Some [ret_node]) ~exn:None ) ; - let ret_control = - {empty_control with root_nodes= [ret_node]; leaf_nodes= [ret_node]; instrs= []} + let return_stmt stmt ~mk_ret_instrs = + let ret_typ_of_pdesc = Procdesc.get_ret_type procdesc in + let ret_exp, ret_typ, var_control = + match context.CContext.return_param_typ with + | Some ret_param_typ -> + let name = CFrontend_config.return_param in + let pvar = Pvar.mk (Mangled.from_string name) procname in + let id = Ident.create_fresh Ident.knormal in + let instr = + Sil.Load + {id; e= Exp.Lvar pvar; root_typ= ret_param_typ; typ= ret_param_typ; loc= sil_loc} + in + let ret_typ = + match ret_param_typ.desc with Typ.Tptr (t, _) -> t | _ -> assert false + in + (Exp.Var id, ret_typ, Some {empty_control with instrs= [instr]}) + | None -> + (Exp.Lvar (Procdesc.get_ret_var procdesc), ret_typ_of_pdesc, None) + in + let trans_state' = + {trans_state_pri with succ_nodes= []; var_exp_typ= Some (ret_exp, ret_typ)} + in + L.debug Capture Verbose "Evaluating sub-expr of return@\n" ; + let res_trans_stmt = instruction trans_state' stmt in + L.debug Capture Verbose "Done evaluating sub-expr of return@\n" ; + let controls = + let var_control = + Option.map var_control ~f:(fun control -> + (* force node creation to place the load instruction [var_control] before the + translation of the sub-expr *) + let trans_state = PriorityNode.force_claim_priority_node trans_state_pri stmt_info in + PriorityNode.compute_control_to_parent trans_state sil_loc ReturnStmt stmt_info + control ) in - PriorityNode.compute_controls_to_parent trans_state_pri sil_loc ReturnStmt stmt_info - [controls; ret_control] - |> mk_trans_result res_trans_stmt.return - | [] -> + PriorityNode.compute_controls_to_parent trans_state' sil_loc ReturnStmt stmt_info + (Option.to_list var_control @ [res_trans_stmt.control]) + in + let ret_instrs = mk_ret_instrs ret_exp ret_typ_of_pdesc ret_typ res_trans_stmt in + let ret_node = mk_ret_node ret_instrs in + L.debug Capture Verbose "Created return node %a with instrs [%a]@\n" Procdesc.Node.pp ret_node + (Pp.seq ~sep:";" (Sil.pp_instr ~print_types:false Pp.text)) + ret_instrs ; + assert (List.is_empty controls.instrs) ; + List.iter controls.leaf_nodes ~f:(fun leaf -> + Procdesc.set_succs leaf ~normal:(Some [ret_node]) ~exn:None ) ; + let ret_control = + {empty_control with root_nodes= [ret_node]; leaf_nodes= [ret_node]; instrs= []} + in + PriorityNode.compute_controls_to_parent trans_state_pri sil_loc ReturnStmt stmt_info + [controls; ret_control] + |> mk_trans_result res_trans_stmt.return + in + match (stmt_list, context.CContext.return_param_typ) with + | ( ([Clang_ast_t.ImplicitCastExpr (_, [stmt], _, _)] | [stmt]) + , Some {desc= Tptr ({desc= Tstruct (CStruct _ as struct_name)}, _)} ) -> + (* return (exp:struct); *) + return_stmt stmt ~mk_ret_instrs:(fun ret_exp _root_typ ret_typ res_trans_stmt -> + struct_copy context.CContext.tenv sil_loc ret_exp (fst res_trans_stmt.return) ret_typ + struct_name ) + | [stmt], _ -> + (* return exp; *) + return_stmt stmt ~mk_ret_instrs:(fun ret_exp root_typ ret_typ res_trans_stmt -> + if List.exists ~f:(Exp.equal ret_exp) res_trans_stmt.control.initd_exps then [] + else + let sil_expr, _ = res_trans_stmt.return in + [Sil.Store {e1= ret_exp; root_typ; typ= ret_typ; e2= sil_expr; loc= sil_loc}] ) + | [], _ -> (* return; *) let ret_node = mk_ret_node [] in mk_trans_result (mk_fresh_void_exp_typ ()) {empty_control with root_nodes= [ret_node]} - | _ -> + | _, _ -> assert false diff --git a/infer/tests/codetoanalyze/c/bufferoverrun/issues.exp b/infer/tests/codetoanalyze/c/bufferoverrun/issues.exp index 78bb62c39..f3cd92501 100644 --- a/infer/tests/codetoanalyze/c/bufferoverrun/issues.exp +++ b/infer/tests/codetoanalyze/c/bufferoverrun/issues.exp @@ -297,6 +297,12 @@ codetoanalyze/c/bufferoverrun/sizeof.c, eval_sizeof_bad, 1, CONDITION_ALWAYS_TRU codetoanalyze/c/bufferoverrun/sizeof.c, eval_sizeof_bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 1 Size: 0] codetoanalyze/c/bufferoverrun/sizeof.c, static_stride_bad, 5, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, [Here] codetoanalyze/c/bufferoverrun/sizeof.c, static_stride_bad, 7, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 1 Size: 0] +codetoanalyze/c/bufferoverrun/struct_copy.c, nested_struct_copy_Bad, 7, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 3] +codetoanalyze/c/bufferoverrun/struct_copy.c, struct_copy_Bad, 6, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 3] +codetoanalyze/c/bufferoverrun/struct_copy.c, struct_copy_decl_Bad, 6, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 3] +codetoanalyze/c/bufferoverrun/struct_copy.c, struct_copy_decl_by_function_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 3] +codetoanalyze/c/bufferoverrun/struct_copy.c, struct_copy_from_function_call_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 3] +codetoanalyze/c/bufferoverrun/struct_copy.c, struct_copy_from_wrapper_call_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Call,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 3] codetoanalyze/c/bufferoverrun/trivial.c, differentiate_array_info_Bad, 8, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Assignment,Array access: Offset: 5 Size: 5] codetoanalyze/c/bufferoverrun/trivial.c, differentiate_array_info_Bad, 8, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Assignment,Array access: Offset: 10 (⇐ 5 + 5) Size: 10] codetoanalyze/c/bufferoverrun/trivial.c, malloc_zero_Bad, 2, INFERBO_ALLOC_IS_ZERO, no_bucket, ERROR, [Allocation: Length: 0] diff --git a/infer/tests/codetoanalyze/c/bufferoverrun/struct_copy.c b/infer/tests/codetoanalyze/c/bufferoverrun/struct_copy.c new file mode 100644 index 000000000..4c7f321ad --- /dev/null +++ b/infer/tests/codetoanalyze/c/bufferoverrun/struct_copy.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +struct s { + int a; + int b; +}; + +void struct_copy_Ok() { + int a[5]; + struct s x, y; + x.a = 3; + x.b = 5; + y = x; + a[y.a] = 0; +} + +void struct_copy_Bad() { + int a[3]; + struct s x, y; + x.a = 3; + x.b = 5; + y = x; + a[y.b] = 0; +} + +struct t { + struct s s; + int c; +}; + +void nested_struct_copy_Ok() { + int a[7]; + struct t x, y; + x.s.a = 3; + x.s.b = 5; + x.c = 7; + y = x; + a[y.s.a] = 0; +} + +void nested_struct_copy_Bad() { + int a[3]; + struct t x, y; + x.s.a = 3; + x.s.b = 5; + x.c = 7; + y = x; + a[y.s.b] = 0; +} + +struct s get_struct() { + struct s x; + x.a = 3; + x.b = 5; + return x; +} + +void struct_copy_from_function_call_Ok() { + int a[5]; + struct s x; + x = get_struct(); + a[x.a] = 0; +} + +void struct_copy_from_function_call_Bad() { + int a[3]; + struct s x; + x = get_struct(); + a[x.b] = 0; +} + +struct s get_struct_wrapper() { + return get_struct(); +} + +void struct_copy_from_wrapper_call_Ok() { + int a[5]; + struct s x; + x = get_struct_wrapper(); + a[x.a] = 0; +} + +void struct_copy_from_wrapper_call_Bad() { + int a[3]; + struct s x; + x = get_struct_wrapper(); + a[x.b] = 0; +} + +void struct_copy_decl_Ok() { + int a[5]; + struct s x; + x.a = 3; + x.b = 5; + struct s y = x; + a[y.a] = 0; +} + +void struct_copy_decl_Bad() { + int a[3]; + struct s x; + x.a = 3; + x.b = 5; + struct s y = x; + a[y.b] = 0; +} + +void struct_copy_decl_by_function_Ok() { + int a[5]; + struct s x = get_struct(); + a[x.a] = 0; +} + +void struct_copy_decl_by_function_Bad() { + int a[3]; + struct s x = get_struct(); + a[x.b] = 0; +} diff --git a/infer/tests/codetoanalyze/c/frontend/initialization/compound_literal.c.dot b/infer/tests/codetoanalyze/c/frontend/initialization/compound_literal.c.dot index fe214fb12..0176e927c 100644 --- a/infer/tests/codetoanalyze/c/frontend/initialization/compound_literal.c.dot +++ b/infer/tests/codetoanalyze/c/frontend/initialization/compound_literal.c.dot @@ -30,7 +30,7 @@ digraph cfg { "init_with_compound_literal.745ef6cf3c32f7f18974c2c4fc6a8c9c_4" -> "init_with_compound_literal.745ef6cf3c32f7f18974c2c4fc6a8c9c_2" ; -"init_with_compound_literal.745ef6cf3c32f7f18974c2c4fc6a8c9c_5" [label="5: DeclStmt \n VARIABLE_DECLARED(p:point); [line 16, column 3]\n *&p.x:int=32 [line 16, column 34]\n *&p.y:int=52 [line 16, column 34]\n n$1=*&p:point [line 16, column 20]\n " shape="box"] +"init_with_compound_literal.745ef6cf3c32f7f18974c2c4fc6a8c9c_5" [label="5: DeclStmt \n VARIABLE_DECLARED(p:point); [line 16, column 3]\n *&p.x:int=32 [line 16, column 34]\n *&p.y:int=52 [line 16, column 34]\n " shape="box"] "init_with_compound_literal.745ef6cf3c32f7f18974c2c4fc6a8c9c_5" -> "init_with_compound_literal.745ef6cf3c32f7f18974c2c4fc6a8c9c_3" ; diff --git a/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.c.dot b/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.c.dot index e582147f9..7ee1b0bd0 100644 --- a/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.c.dot +++ b/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.c.dot @@ -30,7 +30,7 @@ digraph cfg { "foo.acbd18db4cc2f85cedef654fccc4a4d8_3" -> "foo.acbd18db4cc2f85cedef654fccc4a4d8_2" ; -"implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_1" [label="1: Start implicit_expr_set_correctly\nFormals: \nLocals: imageDrawRect:rect \n " color=yellow style=filled] +"implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_1" [label="1: Start implicit_expr_set_correctly\nFormals: \nLocals: 0$?%__sil_tmpSIL_compound_literal__n$1:rect imageDrawRect:rect \n " color=yellow style=filled] "implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_1" -> "implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_5" ; @@ -45,7 +45,7 @@ digraph cfg { "implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_4" -> "implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_2" ; -"implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_5" [label="5: BinaryOperatorStmt: Assign \n *&imageDrawRect.origin.x.a:int=0 [line 56, column 35]\n *&imageDrawRect.origin.x.b:int=0 [line 56, column 35]\n *&imageDrawRect.origin.y:int=0 [line 56, column 35]\n *&imageDrawRect.z:int=0 [line 56, column 35]\n *&imageDrawRect.size:int=5 [line 56, column 25]\n n$1=*&imageDrawRect:rect [line 56, column 19]\n " shape="box"] +"implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_5" [label="5: BinaryOperatorStmt: Assign \n *&0$?%__sil_tmpSIL_compound_literal__n$1.origin.x.a:int=0 [line 56, column 35]\n *&0$?%__sil_tmpSIL_compound_literal__n$1.origin.x.b:int=0 [line 56, column 35]\n *&0$?%__sil_tmpSIL_compound_literal__n$1.origin.y:int=0 [line 56, column 35]\n *&0$?%__sil_tmpSIL_compound_literal__n$1.z:int=0 [line 56, column 35]\n *&0$?%__sil_tmpSIL_compound_literal__n$1.size:int=5 [line 56, column 25]\n n$2=*&0$?%__sil_tmpSIL_compound_literal__n$1.origin.x.a:int [line 56, column 3]\n *&imageDrawRect.origin.x.a:int=n$2 [line 56, column 3]\n n$3=*&0$?%__sil_tmpSIL_compound_literal__n$1.origin.x.b:int [line 56, column 3]\n *&imageDrawRect.origin.x.b:int=n$3 [line 56, column 3]\n n$4=*&0$?%__sil_tmpSIL_compound_literal__n$1.origin.y:int [line 56, column 3]\n *&imageDrawRect.origin.y:int=n$4 [line 56, column 3]\n n$5=*&0$?%__sil_tmpSIL_compound_literal__n$1.z:int [line 56, column 3]\n *&imageDrawRect.z:int=n$5 [line 56, column 3]\n n$6=*&0$?%__sil_tmpSIL_compound_literal__n$1.size:int [line 56, column 3]\n *&imageDrawRect.size:int=n$6 [line 56, column 3]\n " shape="box"] "implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_5" -> "implicit_expr_set_correctly.dcfe49f71ad24e86323cbad97b1a70fe_3" ; @@ -60,7 +60,7 @@ digraph cfg { "main.fad58de7366495db4650cfefac2fcd61_3" -> "main.fad58de7366495db4650cfefac2fcd61_2" ; -"point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_1" [label="1: Start point_coords_set_correctly\nFormals: p:Point*\nLocals: \n " color=yellow style=filled] +"point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_1" [label="1: Start point_coords_set_correctly\nFormals: p:Point*\nLocals: 0$?%__sil_tmpSIL_compound_literal__n$2:Point \n " color=yellow style=filled] "point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_1" -> "point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_5" ; @@ -75,7 +75,7 @@ digraph cfg { "point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_4" -> "point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_2" ; -"point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_5" [label="5: BinaryOperatorStmt: Assign \n n$2=*&p:Point* [line 18, column 4]\n *n$2.x:int=4 [line 18, column 15]\n *n$2.y:int=5 [line 18, column 15]\n n$3=*n$2:Point [line 18, column 8]\n " shape="box"] +"point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_5" [label="5: BinaryOperatorStmt: Assign \n n$3=*&p:Point* [line 18, column 4]\n *&0$?%__sil_tmpSIL_compound_literal__n$2.x:int=4 [line 18, column 15]\n *&0$?%__sil_tmpSIL_compound_literal__n$2.y:int=5 [line 18, column 15]\n n$4=*&0$?%__sil_tmpSIL_compound_literal__n$2.x:int [line 18, column 3]\n *n$3.x:int=n$4 [line 18, column 3]\n n$5=*&0$?%__sil_tmpSIL_compound_literal__n$2.y:int [line 18, column 3]\n *n$3.y:int=n$5 [line 18, column 3]\n " shape="box"] "point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_5" -> "point_coords_set_correctly.3abf7d8dcf379339f0fa9b69df909b28_3" ; diff --git a/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.m.dot b/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.m.dot index 115842ef2..b4ff75f49 100644 --- a/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.m.dot +++ b/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.m.dot @@ -22,7 +22,7 @@ digraph cfg { "struct_init_test.b3909a459f16e15611cc425c52c74b0c_3" -> "struct_init_test.b3909a459f16e15611cc425c52c74b0c_4" ; -"struct_init_test.b3909a459f16e15611cc425c52c74b0c_4" [label="4: Return Stmt \n *n$0.a:double=-1 [line 27, column 29]\n *n$0.b:double=0 [line 27, column 29]\n *n$0.c:double=-0 [line 27, column 29]\n *n$0.d:double=-1 [line 27, column 29]\n *n$0.tx:double=0. [line 27, column 62]\n *n$0.ty:double=0. [line 27, column 62]\n n$1=*n$0:CGAffineTransform [line 27, column 10]\n " shape="box"] +"struct_init_test.b3909a459f16e15611cc425c52c74b0c_4" [label="4: Return Stmt \n *n$0.a:double=-1 [line 27, column 29]\n *n$0.b:double=0 [line 27, column 29]\n *n$0.c:double=-0 [line 27, column 29]\n *n$0.d:double=-1 [line 27, column 29]\n *n$0.tx:double=0. [line 27, column 62]\n *n$0.ty:double=0. [line 27, column 62]\n " shape="box"] "struct_init_test.b3909a459f16e15611cc425c52c74b0c_4" -> "struct_init_test.b3909a459f16e15611cc425c52c74b0c_5" ;