Translate C++ constructors after new

Reviewed By: akotulski

Differential Revision: D3069663

fb-gh-sync-id: c1d794c
shipit-source-id: c1d794c
master
Dulma Rodriguez 9 years ago committed by Facebook Github Bot 9
parent 037c257c4f
commit c6524d799f

@ -55,6 +55,8 @@ let json = ref ""
let pointer_decl_index = ref Clang_ast_main.PointerMap.empty let pointer_decl_index = ref Clang_ast_main.PointerMap.empty
let pointer_stmt_index = ref Clang_ast_main.PointerMap.empty
let debug_mode = ref false let debug_mode = ref false
let stats_mode = ref false let stats_mode = ref false

@ -47,6 +47,8 @@ val json : string ref
val pointer_decl_index : Clang_ast_t.decl Clang_ast_main.PointerMap.t ref val pointer_decl_index : Clang_ast_t.decl Clang_ast_main.PointerMap.t ref
val pointer_stmt_index : Clang_ast_t.stmt Clang_ast_main.PointerMap.t ref
val objc_object : string val objc_object : string
val id_cl : string val id_cl : string

@ -274,6 +274,16 @@ struct
| Some decl_ptr -> get_decl decl_ptr | Some decl_ptr -> get_decl decl_ptr
| None -> None | None -> None
let get_stmt stmt_ptr =
try
Some (Clang_ast_main.PointerMap.find stmt_ptr !CFrontend_config.pointer_stmt_index)
with Not_found -> Printing.log_stats "stmt with pointer %d not found\n" stmt_ptr; None
let get_stmt_opt stmt_ptr_opt =
match stmt_ptr_opt with
| Some stmt_ptr -> get_stmt stmt_ptr
| None -> None
let get_decl_opt_with_decl_ref decl_ref_opt = let get_decl_opt_with_decl_ref decl_ref_opt =
match decl_ref_opt with match decl_ref_opt with
| Some decl_ref -> get_decl decl_ref.Clang_ast_t.dr_decl_pointer | Some decl_ref -> get_decl decl_ref.Clang_ast_t.dr_decl_pointer

@ -75,6 +75,10 @@ sig
val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option
val get_stmt : Clang_ast_t.pointer -> Clang_ast_t.stmt option
val get_stmt_opt : Clang_ast_t.pointer option -> Clang_ast_t.stmt option
val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option
val update_sil_types_map : Clang_ast_t.type_ptr -> Sil.typ -> unit val update_sil_types_map : Clang_ast_t.type_ptr -> Sil.typ -> unit

@ -122,8 +122,9 @@ let do_run source_path ast_path =
| Some path -> path, validate_decl_from_file path | Some path -> path, validate_decl_from_file path
| None -> "stdin of " ^ source_path, validate_decl_from_stdin () in | None -> "stdin of " ^ source_path, validate_decl_from_stdin () in
let decl_index, _, type_index = Clang_ast_main.index_node_pointers ast_decl in let decl_index, stmt_index, type_index = Clang_ast_main.index_node_pointers ast_decl in
CFrontend_config.pointer_decl_index := decl_index; CFrontend_config.pointer_decl_index := decl_index;
CFrontend_config.pointer_stmt_index := stmt_index;
CFrontend_config.pointer_type_index := type_index; CFrontend_config.pointer_type_index := type_index;
CFrontend_config.json := ast_filename; CFrontend_config.json := ast_filename;
CLocation.check_source_file source_path; CLocation.check_source_file source_path;

@ -927,7 +927,10 @@ struct
let class_type = CTypes_decl.get_type_from_expr_info ei context.CContext.tenv in let class_type = CTypes_decl.get_type_from_expr_info ei context.CContext.tenv in
Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, class_type)]; Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, class_type)];
Sil.Lvar pvar, class_type in Sil.Lvar pvar, class_type in
let this_type = Sil.Tptr (class_type, Sil.Pk_pointer) in let this_type =
match class_type with
| Sil.Tptr _ -> class_type
| _ -> Sil.Tptr (class_type, Sil.Pk_pointer) in
let this_res_trans = { empty_res_trans with let this_res_trans = { empty_res_trans with
exps = [(var_exp, this_type)]; exps = [(var_exp, this_type)];
initd_exps = [var_exp]; initd_exps = [var_exp];
@ -1544,7 +1547,10 @@ struct
| _ -> instruction trans_state stmt in | _ -> instruction trans_state stmt in
let res_trans_subexpr_list = IList.map collect_right_hand_exprs stmts in let res_trans_subexpr_list = IList.map collect_right_hand_exprs stmts in
let rh_exps = collect_exprs res_trans_subexpr_list in let rh_exps = collect_exprs res_trans_subexpr_list in
if IList.length rh_exps != IList.length lh then if IList.length rh_exps == 0 then
let exp = Sil.zero_value_of_numerical_type var_type in
{ empty_res_trans with root_nodes = trans_state.succ_nodes; exps = [(exp, typ)]; }
else if IList.length rh_exps != IList.length lh then
(* If the right hand expressions are not as many as the left hand expressions something's wrong *) (* If the right hand expressions are not as many as the left hand expressions something's wrong *)
{ empty_res_trans with root_nodes = trans_state.succ_nodes } { empty_res_trans with root_nodes = trans_state.succ_nodes }
else else
@ -1564,16 +1570,8 @@ struct
{ res_trans_to_parent with exps = initlist_expr_res.exps } { res_trans_to_parent with exps = initlist_expr_res.exps }
and init_expr_trans trans_state var_exp_typ var_stmt_info init_expr_opt = and init_expr_trans trans_state var_exp_typ var_stmt_info init_expr_opt =
let open Clang_ast_t in
match init_expr_opt with match init_expr_opt with
| None -> { empty_res_trans with root_nodes = trans_state.succ_nodes } (* Nothing to do if no init expression *) | None -> { empty_res_trans with root_nodes = trans_state.succ_nodes } (* Nothing to do if no init expression *)
| Some (ImplicitValueInitExpr (_, stmt_list, _)) ->
(* Seems unclear what it does, so let's keep an eye on the stmts *)
(* and report a warning if it finds a non empty list of stmts *)
(match stmt_list with
| [] -> ()
| _ -> Printing.log_stats "\n!!!!WARNING: found statement <\"ImplicitValueInitExpr\"> with non-empty stmt_list.\n");
{ empty_res_trans with root_nodes = trans_state.succ_nodes }
| Some ie -> (*For init expr, translate how to compute it and assign to the var*) | Some ie -> (*For init expr, translate how to compute it and assign to the var*)
let stmt_info, _ = Clang_ast_proj.get_stmt_tuple ie in let stmt_info, _ = Clang_ast_proj.get_stmt_tuple ie in
let var_exp, _ = var_exp_typ in let var_exp, _ = var_exp_typ in
@ -1926,15 +1924,31 @@ struct
} }
| _ -> assert false | _ -> assert false
and cxxNewExpr_trans trans_state stmt_info expr_info = and cxxNewExpr_trans trans_state stmt_info expr_info cxx_new_expr_info =
let context = trans_state.context in let context = trans_state.context in
let typ = CTypes_decl.get_type_from_expr_info expr_info context.CContext.tenv in let typ = CTypes_decl.get_type_from_expr_info expr_info context.CContext.tenv in
let sil_loc = CLocation.get_sil_location stmt_info context in let sil_loc = CLocation.get_sil_location stmt_info context in
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in
cpp_new_trans trans_state_pri sil_loc stmt_info typ let res_trans_new = cpp_new_trans trans_state_pri sil_loc typ in
if cxx_new_expr_info.Clang_ast_t.xnei_is_array then
assert false (* TODO *)
else
let stmt_opt = Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in
let trans_state_init = { trans_state_pri with succ_nodes = []; } in
let var_exp_typ = match res_trans_new.exps with [exp] -> exp | _ -> assert false in
(* Need a new stmt_info for the translation of the initializer, so that it can create nodes *)
(* if it needs to, with the same stmt_info it doesn't work. *)
let init_stmt_info = { stmt_info with
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in
let res_trans_init =
init_expr_trans trans_state_init var_exp_typ init_stmt_info stmt_opt in
let all_res_trans = [res_trans_new; res_trans_init] in
let nname = "CXXNewExpr" in
let result_trans_to_parent = PriorityNode.compute_results_to_parent trans_state_pri sil_loc
nname stmt_info all_res_trans in
{ result_trans_to_parent with exps = res_trans_new.exps }
(* TODOs 7912220 - no usable information in json as of right now *) (* TODOs 7912220 - no usable information in json as of right now *)
(* 1. Handle __new_array *) (* 1. Handle __new_array *)
(* 2. Handle initialization values *)
and cxxDeleteExpr_trans trans_state stmt_info stmt_list delete_expr_info = and cxxDeleteExpr_trans trans_state stmt_info stmt_list delete_expr_info =
let context = trans_state.context in let context = trans_state.context in
@ -2325,8 +2339,8 @@ struct
"BinaryConditionalOperator not translated %s @." "BinaryConditionalOperator not translated %s @."
(Ast_utils.string_of_stmt instr); (Ast_utils.string_of_stmt instr);
assert false) assert false)
| CXXNewExpr (stmt_info, _, expr_info, _) -> | CXXNewExpr (stmt_info, _, expr_info, cxx_new_expr_info) ->
cxxNewExpr_trans trans_state stmt_info expr_info cxxNewExpr_trans trans_state stmt_info expr_info cxx_new_expr_info
| CXXDeleteExpr (stmt_info, stmt_list, _, delete_expr_info) -> | CXXDeleteExpr (stmt_info, stmt_list, _, delete_expr_info) ->
cxxDeleteExpr_trans trans_state stmt_info stmt_list delete_expr_info cxxDeleteExpr_trans trans_state stmt_info stmt_list delete_expr_info
| MaterializeTemporaryExpr (stmt_info, stmt_list, expr_info, _) -> | MaterializeTemporaryExpr (stmt_info, stmt_list, expr_info, _) ->

@ -348,14 +348,11 @@ let new_or_alloc_trans trans_state loc stmt_info type_ptr class_name_opt selecto
objc_new_trans trans_state loc stmt_info class_name function_type objc_new_trans trans_state loc stmt_info class_name function_type
else assert false else assert false
let cpp_new_trans trans_state sil_loc stmt_info function_type = let cpp_new_trans trans_state sil_loc function_type =
let fname = SymExec.ModelBuiltins.__new in let fname = SymExec.ModelBuiltins.__new in
let (function_type, ret_id, stmt_call, exp) = create_alloc_instrs trans_state.context sil_loc function_type fname in let (function_type, ret_id, stmt_call, exp) =
let res_trans_tmp = { empty_res_trans with ids =[ret_id]; instrs =[stmt_call]} in create_alloc_instrs trans_state.context sil_loc function_type fname in
let res_trans = { empty_res_trans with ids = [ret_id]; instrs = [stmt_call]; exps = [(exp, function_type)] }
let nname = "Call C++ new" in
PriorityNode.compute_results_to_parent trans_state sil_loc nname stmt_info [res_trans_tmp] in
{ res_trans with exps = [(exp, function_type)] }
let create_cast_instrs context exp cast_from_typ cast_to_typ sil_loc = let create_cast_instrs context exp cast_from_typ cast_to_typ sil_loc =
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in

@ -107,7 +107,7 @@ val alloc_trans :
val new_or_alloc_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info -> val new_or_alloc_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info ->
Clang_ast_t.type_ptr -> string option -> string -> trans_result Clang_ast_t.type_ptr -> string option -> string -> trans_result
val cpp_new_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info -> Sil.typ -> trans_result val cpp_new_trans : trans_state -> Location.t -> Sil.typ -> trans_result
val cast_trans : val cast_trans :
CContext.t -> (Sil.exp * Sil.typ) list -> Location.t -> Procname.t option -> Sil.typ -> CContext.t -> (Sil.exp * Sil.typ) list -> Location.t -> Procname.t option -> Sil.typ ->

@ -7,7 +7,7 @@ digraph iCFG {
5 -> 4 ; 5 -> 4 ;
4 [label="4: Call C++ new \n n$1=_fun___new(sizeof(int ):unsigned long ) [line 13]\n REMOVE_TEMPS(n$1); [line 13]\n " shape="box"] 4 [label="4: CXXNewExpr \n n$1=_fun___new(sizeof(int ):unsigned long ) [line 13]\n REMOVE_TEMPS(n$1); [line 13]\n " shape="box"]
4 -> 3 ; 4 -> 3 ;

@ -0,0 +1,72 @@
/*
* Copyright (c) 2016 - 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.
*/
class Person {
public:
Person(int i) { x = i; }
Person(int i, int j, int k) {
x = i;
y = j;
z = k;
}
int x;
int y;
int z;
};
int getValue(int x) { return x; }
int constructor_1_arg_new_div0() {
Person* p = new Person(5);
return 1 / (p->x - 5);
}
int constructor_3_args_new_div0() {
Person* p = new Person(5, 6, 7);
return 1 / (p->z - 7);
}
int int_init_number() {
int* x1 = new int(5);
return 1 / (*x1 - 5);
}
float float_init_number() {
float* x1 = new float(5.4);
return 1 / (*x1 - 5.4);
}
int int_init_empty() {
int* x1 = new int();
return 1 / *x1;
}
int int_init_empty_list() {
int x1{};
return 1 / x1;
}
int int_init_empty_list_new() {
int* x1 = new int{};
return 1 / *x1;
}
int int_init_nodes() {
int z = 6;
int* y = new int(getValue(4));
int* x = new int(getValue(0) ? getValue(1) : 1 + *y);
return 1 / (*x - 5);
}
int constructor_nodes() {
int z = 6;
Person* p = new Person(getValue(0) ? getValue(1) : 1 + z);
return 1 / (p->x - 7);
}

@ -0,0 +1,240 @@
digraph iCFG {
62 [label="62: DeclStmt \n *&z:int =6 [line 69]\n " shape="box"]
62 -> 56 ;
61 [label="61: DeclStmt \n n$2=_fun___new(sizeof(class Person ):unsigned long ) [line 70]\n n$6=*&SIL_temp_conditional___55:int [line 70]\n NULLIFY(&SIL_temp_conditional___55,true); [line 70]\n _fun_Person_Person(n$2:class Person *,n$6:int ) [line 70]\n *&p:class Person *=n$2 [line 70]\n REMOVE_TEMPS(n$2,n$6); [line 70]\n " shape="box"]
61 -> 54 ;
60 [label="60: ConditinalStmt Branch \n n$5=*&z:int [line 70]\n DECLARE_LOCALS(&SIL_temp_conditional___55); [line 70]\n *&SIL_temp_conditional___55:int =(1 + n$5) [line 70]\n REMOVE_TEMPS(n$5); [line 70]\n NULLIFY(&z,false); [line 70]\n APPLY_ABSTRACTION; [line 70]\n " shape="box"]
60 -> 55 ;
59 [label="59: ConditinalStmt Branch \n NULLIFY(&z,false); [line 70]\n n$4=_fun_getValue(1:int ) [line 70]\n DECLARE_LOCALS(&SIL_temp_conditional___55); [line 70]\n *&SIL_temp_conditional___55:int =n$4 [line 70]\n REMOVE_TEMPS(n$4); [line 70]\n APPLY_ABSTRACTION; [line 70]\n " shape="box"]
59 -> 55 ;
58 [label="58: Prune (false branch) \n PRUNE((n$3 == 0), false); [line 70]\n REMOVE_TEMPS(n$3); [line 70]\n " shape="invhouse"]
58 -> 60 ;
57 [label="57: Prune (true branch) \n PRUNE((n$3 != 0), true); [line 70]\n REMOVE_TEMPS(n$3); [line 70]\n " shape="invhouse"]
57 -> 59 ;
56 [label="56: Call _fun_getValue \n n$3=_fun_getValue(0:int ) [line 70]\n " shape="box"]
56 -> 57 ;
56 -> 58 ;
55 [label="55: + \n " ]
55 -> 61 ;
54 [label="54: Return Stmt \n n$0=*&p:class Person * [line 71]\n n$1=*n$0.x:int [line 71]\n *&return:int =(1 / (n$1 - 7)) [line 71]\n REMOVE_TEMPS(n$0,n$1); [line 71]\n NULLIFY(&p,false); [line 71]\n APPLY_ABSTRACTION; [line 71]\n " shape="box"]
54 -> 53 ;
53 [label="53: Exit constructor_nodes \n " color=yellow style=filled]
52 [label="52: Start constructor_nodes\nFormals: \nLocals: p:class Person * z:int \n DECLARE_LOCALS(&return,&p,&z); [line 68]\n NULLIFY(&p,false); [line 68]\n NULLIFY(&z,false); [line 68]\n " color=yellow style=filled]
52 -> 62 ;
51 [label="51: DeclStmt \n *&z:int =6 [line 62]\n NULLIFY(&z,false); [line 62]\n " shape="box"]
51 -> 50 ;
50 [label="50: DeclStmt \n n$8=_fun___new(sizeof(int ):unsigned long ) [line 63]\n n$9=_fun_getValue(4:int ) [line 63]\n *n$8:int =n$9 [line 63]\n *&y:int *=n$8 [line 63]\n REMOVE_TEMPS(n$8,n$9); [line 63]\n " shape="box"]
50 -> 44 ;
49 [label="49: DeclStmt \n n$2=_fun___new(sizeof(int ):unsigned long ) [line 64]\n n$7=*&SIL_temp_conditional___43:int [line 64]\n NULLIFY(&SIL_temp_conditional___43,true); [line 64]\n *n$2:int =n$7 [line 64]\n *&x:int *=n$2 [line 64]\n REMOVE_TEMPS(n$2,n$7); [line 64]\n " shape="box"]
49 -> 42 ;
48 [label="48: ConditinalStmt Branch \n n$5=*&y:int * [line 64]\n n$6=*n$5:int [line 64]\n DECLARE_LOCALS(&SIL_temp_conditional___43); [line 64]\n *&SIL_temp_conditional___43:int =(1 + n$6) [line 64]\n REMOVE_TEMPS(n$5,n$6); [line 64]\n NULLIFY(&y,false); [line 64]\n APPLY_ABSTRACTION; [line 64]\n " shape="box"]
48 -> 43 ;
47 [label="47: ConditinalStmt Branch \n NULLIFY(&y,false); [line 64]\n n$4=_fun_getValue(1:int ) [line 64]\n DECLARE_LOCALS(&SIL_temp_conditional___43); [line 64]\n *&SIL_temp_conditional___43:int =n$4 [line 64]\n REMOVE_TEMPS(n$4); [line 64]\n APPLY_ABSTRACTION; [line 64]\n " shape="box"]
47 -> 43 ;
46 [label="46: Prune (false branch) \n PRUNE((n$3 == 0), false); [line 64]\n REMOVE_TEMPS(n$3); [line 64]\n " shape="invhouse"]
46 -> 48 ;
45 [label="45: Prune (true branch) \n PRUNE((n$3 != 0), true); [line 64]\n REMOVE_TEMPS(n$3); [line 64]\n " shape="invhouse"]
45 -> 47 ;
44 [label="44: Call _fun_getValue \n n$3=_fun_getValue(0:int ) [line 64]\n " shape="box"]
44 -> 45 ;
44 -> 46 ;
43 [label="43: + \n " ]
43 -> 49 ;
42 [label="42: Return Stmt \n n$0=*&x:int * [line 65]\n n$1=*n$0:int [line 65]\n *&return:int =(1 / (n$1 - 5)) [line 65]\n REMOVE_TEMPS(n$0,n$1); [line 65]\n NULLIFY(&x,false); [line 65]\n APPLY_ABSTRACTION; [line 65]\n " shape="box"]
42 -> 41 ;
41 [label="41: Exit int_init_nodes \n " color=yellow style=filled]
40 [label="40: Start int_init_nodes\nFormals: \nLocals: x:int * y:int * z:int \n DECLARE_LOCALS(&return,&x,&y,&z); [line 61]\n NULLIFY(&x,false); [line 61]\n NULLIFY(&y,false); [line 61]\n NULLIFY(&z,false); [line 61]\n " color=yellow style=filled]
40 -> 51 ;
39 [label="39: DeclStmt \n n$2=_fun___new(sizeof(int ):unsigned long ) [line 57]\n *n$2:int *=0 [line 57]\n *&x1:int *=n$2 [line 57]\n REMOVE_TEMPS(n$2); [line 57]\n " shape="box"]
39 -> 38 ;
38 [label="38: Return Stmt \n n$0=*&x1:int * [line 58]\n n$1=*n$0:int [line 58]\n *&return:int =(1 / n$1) [line 58]\n REMOVE_TEMPS(n$0,n$1); [line 58]\n NULLIFY(&x1,false); [line 58]\n APPLY_ABSTRACTION; [line 58]\n " shape="box"]
38 -> 37 ;
37 [label="37: Exit int_init_empty_list_new \n " color=yellow style=filled]
36 [label="36: Start int_init_empty_list_new\nFormals: \nLocals: x1:int * \n DECLARE_LOCALS(&return,&x1); [line 56]\n NULLIFY(&x1,false); [line 56]\n " color=yellow style=filled]
36 -> 39 ;
35 [label="35: DeclStmt \n *&x1:int =0 [line 52]\n " shape="box"]
35 -> 34 ;
34 [label="34: Return Stmt \n n$0=*&x1:int [line 53]\n *&return:int =(1 / n$0) [line 53]\n REMOVE_TEMPS(n$0); [line 53]\n NULLIFY(&x1,false); [line 53]\n APPLY_ABSTRACTION; [line 53]\n " shape="box"]
34 -> 33 ;
33 [label="33: Exit int_init_empty_list \n " color=yellow style=filled]
32 [label="32: Start int_init_empty_list\nFormals: \nLocals: x1:int \n DECLARE_LOCALS(&return,&x1); [line 51]\n NULLIFY(&x1,false); [line 51]\n " color=yellow style=filled]
32 -> 35 ;
31 [label="31: DeclStmt \n n$2=_fun___new(sizeof(int ):unsigned long ) [line 47]\n *n$2:int =0 [line 47]\n *&x1:int *=n$2 [line 47]\n REMOVE_TEMPS(n$2); [line 47]\n " shape="box"]
31 -> 30 ;
30 [label="30: Return Stmt \n n$0=*&x1:int * [line 48]\n n$1=*n$0:int [line 48]\n *&return:int =(1 / n$1) [line 48]\n REMOVE_TEMPS(n$0,n$1); [line 48]\n NULLIFY(&x1,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"]
30 -> 29 ;
29 [label="29: Exit int_init_empty \n " color=yellow style=filled]
28 [label="28: Start int_init_empty\nFormals: \nLocals: x1:int * \n DECLARE_LOCALS(&return,&x1); [line 46]\n NULLIFY(&x1,false); [line 46]\n " color=yellow style=filled]
28 -> 31 ;
27 [label="27: DeclStmt \n n$2=_fun___new(sizeof(float ):unsigned long ) [line 42]\n *n$2:float =5.400000 [line 42]\n *&x1:float *=n$2 [line 42]\n REMOVE_TEMPS(n$2); [line 42]\n " shape="box"]
27 -> 26 ;
26 [label="26: Return Stmt \n n$0=*&x1:float * [line 43]\n n$1=*n$0:float [line 43]\n *&return:float =(1 / (n$1 - 5.400000)) [line 43]\n REMOVE_TEMPS(n$0,n$1); [line 43]\n NULLIFY(&x1,false); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"]
26 -> 25 ;
25 [label="25: Exit float_init_number \n " color=yellow style=filled]
24 [label="24: Start float_init_number\nFormals: \nLocals: x1:float * \n DECLARE_LOCALS(&return,&x1); [line 41]\n NULLIFY(&x1,false); [line 41]\n " color=yellow style=filled]
24 -> 27 ;
23 [label="23: DeclStmt \n n$2=_fun___new(sizeof(int ):unsigned long ) [line 37]\n *n$2:int =5 [line 37]\n *&x1:int *=n$2 [line 37]\n REMOVE_TEMPS(n$2); [line 37]\n " shape="box"]
23 -> 22 ;
22 [label="22: Return Stmt \n n$0=*&x1:int * [line 38]\n n$1=*n$0:int [line 38]\n *&return:int =(1 / (n$1 - 5)) [line 38]\n REMOVE_TEMPS(n$0,n$1); [line 38]\n NULLIFY(&x1,false); [line 38]\n APPLY_ABSTRACTION; [line 38]\n " shape="box"]
22 -> 21 ;
21 [label="21: Exit int_init_number \n " color=yellow style=filled]
20 [label="20: Start int_init_number\nFormals: \nLocals: x1:int * \n DECLARE_LOCALS(&return,&x1); [line 36]\n NULLIFY(&x1,false); [line 36]\n " color=yellow style=filled]
20 -> 23 ;
19 [label="19: DeclStmt \n n$2=_fun___new(sizeof(class Person ):unsigned long ) [line 32]\n _fun_Person_Person(n$2:class Person *,5:int ,6:int ,7:int ) [line 32]\n *&p:class Person *=n$2 [line 32]\n REMOVE_TEMPS(n$2); [line 32]\n " shape="box"]
19 -> 18 ;
18 [label="18: Return Stmt \n n$0=*&p:class Person * [line 33]\n n$1=*n$0.z:int [line 33]\n *&return:int =(1 / (n$1 - 7)) [line 33]\n REMOVE_TEMPS(n$0,n$1); [line 33]\n NULLIFY(&p,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"]
18 -> 17 ;
17 [label="17: Exit constructor_3_args_new_div0 \n " color=yellow style=filled]
16 [label="16: Start constructor_3_args_new_div0\nFormals: \nLocals: p:class Person * \n DECLARE_LOCALS(&return,&p); [line 31]\n NULLIFY(&p,false); [line 31]\n " color=yellow style=filled]
16 -> 19 ;
15 [label="15: DeclStmt \n n$2=_fun___new(sizeof(class Person ):unsigned long ) [line 27]\n _fun_Person_Person(n$2:class Person *,5:int ) [line 27]\n *&p:class Person *=n$2 [line 27]\n REMOVE_TEMPS(n$2); [line 27]\n " shape="box"]
15 -> 14 ;
14 [label="14: Return Stmt \n n$0=*&p:class Person * [line 28]\n n$1=*n$0.x:int [line 28]\n *&return:int =(1 / (n$1 - 5)) [line 28]\n REMOVE_TEMPS(n$0,n$1); [line 28]\n NULLIFY(&p,false); [line 28]\n APPLY_ABSTRACTION; [line 28]\n " shape="box"]
14 -> 13 ;
13 [label="13: Exit constructor_1_arg_new_div0 \n " color=yellow style=filled]
12 [label="12: Start constructor_1_arg_new_div0\nFormals: \nLocals: p:class Person * \n DECLARE_LOCALS(&return,&p); [line 26]\n NULLIFY(&p,false); [line 26]\n " color=yellow style=filled]
12 -> 15 ;
11 [label="11: Return Stmt \n n$0=*&x:int [line 24]\n *&return:int =n$0 [line 24]\n REMOVE_TEMPS(n$0); [line 24]\n NULLIFY(&x,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"]
11 -> 10 ;
10 [label="10: Exit getValue \n " color=yellow style=filled]
9 [label="9: Start getValue\nFormals: x:int \nLocals: \n DECLARE_LOCALS(&return); [line 24]\n " color=yellow style=filled]
9 -> 11 ;
8 [label="8: BinaryOperatorStmt: Assign \n n$4=*&this:class Person * [line 15]\n n$5=*&i:int [line 15]\n *n$4.x:int =n$5 [line 15]\n REMOVE_TEMPS(n$4,n$5); [line 15]\n NULLIFY(&i,false); [line 15]\n " shape="box"]
8 -> 7 ;
7 [label="7: BinaryOperatorStmt: Assign \n n$2=*&this:class Person * [line 16]\n n$3=*&j:int [line 16]\n *n$2.y:int =n$3 [line 16]\n REMOVE_TEMPS(n$2,n$3); [line 16]\n NULLIFY(&j,false); [line 16]\n " shape="box"]
7 -> 6 ;
6 [label="6: BinaryOperatorStmt: Assign \n n$0=*&this:class Person * [line 17]\n n$1=*&k:int [line 17]\n *n$0.z:int =n$1 [line 17]\n REMOVE_TEMPS(n$0,n$1); [line 17]\n NULLIFY(&k,false); [line 17]\n NULLIFY(&this,false); [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit Person_Person \n " color=yellow style=filled]
4 [label="4: Start Person_Person\nFormals: this:class Person * i:int j:int k:int \nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled]
4 -> 8 ;
3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&this:class Person * [line 12]\n n$1=*&i:int [line 12]\n *n$0.x:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&i,false); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit Person_Person \n " color=yellow style=filled]
1 [label="1: Start Person_Person\nFormals: this:class Person * i:int \nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -10,7 +10,7 @@
struct X { struct X {
int a = -1; int a = -1;
int b{-2}; int b{-2};
int c{}; // doesn't work yet int c{};
int d; int d;
X() = default; X() = default;
X(int a, int b) : a(a + b) {} X(int a, int b) : a(a + b) {}

@ -37,7 +37,7 @@ digraph iCFG {
9 -> 8 ; 9 -> 8 ;
8 [label="8: Constructor Init \n n$0=*&this:class X * [line 13]\n *n$0.c:int =-1 [line 16]\n REMOVE_TEMPS(n$0); [line 16]\n NULLIFY(&this,false); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"] 8 [label="8: Constructor Init \n n$0=*&this:class X * [line 13]\n *n$0.c:int =0 [line 16]\n REMOVE_TEMPS(n$0); [line 16]\n NULLIFY(&this,false); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
8 -> 7 ; 8 -> 7 ;
@ -56,7 +56,7 @@ digraph iCFG {
4 -> 3 ; 4 -> 3 ;
3 [label="3: Constructor Init \n n$0=*&this:class X * [line 13]\n *n$0.c:int =-1 [line 15]\n REMOVE_TEMPS(n$0); [line 15]\n NULLIFY(&this,false); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] 3 [label="3: Constructor Init \n n$0=*&this:class X * [line 13]\n *n$0.c:int =0 [line 15]\n REMOVE_TEMPS(n$0); [line 15]\n NULLIFY(&this,false); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"]
3 -> 2 ; 3 -> 2 ;

@ -1,5 +1,5 @@
digraph iCFG { digraph iCFG {
53 [label="53: DeclStmt \n n$2=_fun___new(sizeof(class Triangle ):unsigned long ) [line 71]\n *&trgl:class Triangle *=n$2 [line 71]\n REMOVE_TEMPS(n$2); [line 71]\n " shape="box"] 53 [label="53: DeclStmt \n n$2=_fun___new(sizeof(class Triangle ):unsigned long ) [line 71]\n _fun_Triangle_Triangle(n$2:class Triangle *) [line 71]\n *&trgl:class Triangle *=n$2 [line 71]\n REMOVE_TEMPS(n$2); [line 71]\n " shape="box"]
53 -> 52 ; 53 -> 52 ;

@ -1,13 +1,13 @@
digraph iCFG { digraph iCFG {
25 [label="25: DeclStmt \n n$20=_fun___new(sizeof(class Base ):unsigned long ) [line 22]\n *&b:class Base *=n$20 [line 22]\n REMOVE_TEMPS(n$20); [line 22]\n " shape="box"] 25 [label="25: DeclStmt \n n$20=_fun___new(sizeof(class Base ):unsigned long ) [line 22]\n _fun_Base_Base(n$20:class Base *) [line 22]\n *&b:class Base *=n$20 [line 22]\n REMOVE_TEMPS(n$20); [line 22]\n " shape="box"]
25 -> 24 ; 25 -> 24 ;
24 [label="24: DeclStmt \n n$19=_fun___new(sizeof(class Sub ):unsigned long ) [line 23]\n *&s1:class Sub *=n$19 [line 23]\n REMOVE_TEMPS(n$19); [line 23]\n " shape="box"] 24 [label="24: DeclStmt \n n$19=_fun___new(sizeof(class Sub ):unsigned long ) [line 23]\n _fun_Sub_Sub(n$19:class Sub *) [line 23]\n *&s1:class Sub *=n$19 [line 23]\n REMOVE_TEMPS(n$19); [line 23]\n " shape="box"]
24 -> 23 ; 24 -> 23 ;
23 [label="23: DeclStmt \n n$18=_fun___new(sizeof(class Sub ):unsigned long ) [line 24]\n *&s2:class Sub *=n$18 [line 24]\n REMOVE_TEMPS(n$18); [line 24]\n " shape="box"] 23 [label="23: DeclStmt \n n$18=_fun___new(sizeof(class Sub ):unsigned long ) [line 24]\n _fun_Sub_Sub(n$18:class Sub *) [line 24]\n *&s2:class Sub *=n$18 [line 24]\n REMOVE_TEMPS(n$18); [line 24]\n " shape="box"]
23 -> 22 ; 23 -> 22 ;

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016 - 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.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferResults;
import utils.InferRunner;
public class ConstructorNewTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_new.cpp";
private static ImmutableList<String> inferCmd;
public static final String DIVIDE_BY_ZERO = "DIVIDE_BY_ZERO";
@ClassRule
public static DebuggableTemporaryFolder folder =
new DebuggableTemporaryFolder();
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsOnDiv0MethodsErrorIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
String[] procedures = {
"constructor_1_arg_new_div0",
"constructor_3_args_new_div0",
"int_init_number",
"float_init_number",
"int_init_empty",
"int_init_empty_list",
"int_init_empty_list_new",
"int_init_nodes",
"constructor_nodes"
};
assertThat(
"Results should contain the expected divide by zero",
inferResults,
containsExactly(
DIVIDE_BY_ZERO,
FILE,
procedures
)
);
}
}

@ -76,4 +76,10 @@ public class ConstructorsTest {
throws InterruptedException, IOException, InferException { throws InterruptedException, IOException, InferException {
frontendTest("std_init_list.cpp"); frontendTest("std_init_list.cpp");
} }
@Test
public void testConstructorNewFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("constructor_new.cpp");
}
} }

Loading…
Cancel
Save