Fix type information about reference types in CFGs

Summary: public Two cases were not handled properly so far:
1. Declaration of a reference variable missed reference bit in type
2. Parameters to a function expecting T& had type T.

The way to distinguish reference types from value types is to look
whether parameter is type 'T rvalue' or type 'T lvalue' (xvalue probably as well)
Unfortunately, we can't just say 'T lvalue' = 'T&' because it would break
a lot of things in our frontend.

However, we know that when parameter to a function call has type 'T lvalue', it has to be 'T&' type.
Same applies when init_expression type is lvalue.

So, the solution is to add wrapper function that looks at results of `instruction` function and
expected expression type. Then if it's lvalue, wrap the type in reference.
Do this wrapping magic only when we know that lvalue mean reference type.

The rest of the changes is to make frontend tests pass - since we use different fields
in the AST, some of them were incorrectly set before and no one noticed.

Reviewed By: cristianoc

Differential Revision: D2549991

fb-gh-sync-id: 067f5d5
master
Andrzej Kotulski 9 years ago committed by facebook-github-bot-7
parent 596401856d
commit b86af1e5d1

@ -389,7 +389,7 @@ let translate_dispatch_function block_name stmt_info stmt_list ei n =
di_source_range = stmt_info.si_source_range } in
let stmt_info = { stmt_info with si_pointer = Ast_utils.get_fresh_pointer(); } in
let var_decl_info = { empty_var_decl_info with vdi_init_expr = Some block_def} in
let block_var_decl = VarDecl(decl_info, block_name_info, ei.ei_type_ptr, var_decl_info) in
let block_var_decl = VarDecl(decl_info, block_name_info, tp, var_decl_info) in
let decl_stmt = DeclStmt(stmt_info,[], [block_var_decl]) in
let expr_info_call = make_general_expr_info create_void_star_type `XValue `Ordinary in
@ -515,7 +515,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let type_opt = Some create_BOOL_type in
let parameter = Clang_ast_t.UnaryExprOrTypeTraitExpr
((fresh_stmt_info stmt_info), [],
make_expr_info create_unsigned_long_type,
make_general_expr_info create_unsigned_long_type `RValue `Ordinary,
{ Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_type_ptr = type_opt}) in
let pointer = di.Clang_ast_t.di_pointer in
let stmt_info = fresh_stmt_info stmt_info in
@ -576,7 +576,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let open Clang_ast_t in
match pobj with
| ParmVarDecl(di_obj, name_obj, tp_obj, _) ->
let poe_ei = make_general_expr_info tp_obj `LValue `Ordinary in
let poe_ei = make_general_expr_info tp_obj `RValue `Ordinary in
let ei_array = get_ei_from_cast decl_ref_expr_array in
let ove_array = build_OpaqueValueExpr (fresh_stmt_info stmt_info) decl_ref_expr_array ei_array in
let ei_idx = get_ei_from_cast decl_ref_expr_idx in
@ -697,7 +697,8 @@ let create_assume_not_null_call decl_info var_name var_type =
let cast_info_call = { Clang_ast_t.cei_cast_kind = `LValueToRValue; cei_base_path = [] } in
let decl_ref_exp_cast = Clang_ast_t.ImplicitCastExpr (stmt_info, [var_decl_ref], expr_info, cast_info_call) in
let null_expr = create_integer_literal stmt_info "0" in
let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info (make_lvalue_obc_prop_expr_info var_type) boi in
let bin_op_expr_info = make_general_expr_info create_BOOL_type `RValue `Ordinary in
let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info bin_op_expr_info boi in
let parameters = [bin_op] in
let procname = Procname.to_string SymExec.ModelBuiltins.__infer_assume in
let qual_procname = Ast_utils.make_name_decl procname in

@ -187,6 +187,17 @@ struct
{ empty_res_trans with
exps = [(Sil.Sizeof(expanded_type, Sil.Subtype.exact), Sil.Tint Sil.IULong)] }
let exec_with_lvalue_as_reference f trans_state stmt =
let expr_info = match Clang_ast_proj.get_expr_tuple stmt with
| Some (_, _, ei) -> ei
| None -> assert false in
let res_trans = f trans_state stmt in
if expr_info.Clang_ast_t.ei_value_kind = `LValue then
let (exp, typ) = extract_exp_from_list res_trans.exps
"[Warning] Need exactly one expression to add reference type\n" in
{ res_trans with exps = [(exp, Sil.Tptr (typ, Sil.Pk_reference))] }
else res_trans
(* Execute translation of e forcing to release priority (if it's not free) and then setting it back.*)
(* This is used in conditional operators where we need to force the priority to be free for the *)
(* computation of the expressions*)
@ -590,7 +601,8 @@ struct
CTrans_utils.assign_default_params params_stmt None fun_exp_stmt ~is_cxx_method:false
else [] in
let res_trans_par =
let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) params_stmt in
let instruction' = exec_with_self_exception (exec_with_lvalue_as_reference instruction) in
let l = list_map (instruction' trans_state_param) params_stmt in
let rt = collect_res_trans (res_trans_callee :: l) in
{ rt with exps = list_tl rt.exps } in
let sil_fe, is_cf_retain_release = CTrans_models.builtin_predefined_model fun_exp_stmt sil_fe in
@ -672,7 +684,8 @@ struct
let trans_state_param =
{ trans_state_pri with parent_line_number = line_number; succ_nodes = [] } in
let result_trans_params =
let l = list_map (exec_with_self_exception instruction trans_state_param) params_stmt in
let instruction' = exec_with_lvalue_as_reference instruction in
let l = list_map (exec_with_self_exception instruction' trans_state_param) params_stmt in
(* this function will automatically merge 'this' argument with rest of arguments in 'l'*)
let rt = collect_res_trans (result_trans_callee :: l) in
{ rt with exps = list_tl rt.exps } in
@ -726,7 +739,9 @@ struct
with Self.SelfClassException class_name ->
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class selector class_name in
obj_c_message_expr_info, empty_res_trans) in
let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) rest in
let instruction' =
exec_with_self_exception (exec_with_lvalue_as_reference instruction) in
let l = list_map (instruction' trans_state_param) rest in
obj_c_message_expr_info, collect_res_trans (fst_res_trans :: l)
| [] -> obj_c_message_expr_info, empty_res_trans) in
let (class_type, _, _, _) = CMethod_trans.get_class_selector_instance context obj_c_message_expr_info res_trans_par.exps in
@ -1412,7 +1427,9 @@ struct
(* if ie is a block the translation need to be done with the block special cases by exec_with_block_priority*)
let res_trans_ie =
let trans_state' = { trans_state_pri with succ_nodes = next_node; parent_line_number = line_number } in
exec_with_block_priority_exception (exec_with_self_exception instruction) trans_state' ie stmt_info in
let instruction' =
exec_with_self_exception (exec_with_lvalue_as_reference instruction) in
exec_with_block_priority_exception instruction' trans_state' ie stmt_info in
let root_nodes = res_trans_ie.root_nodes in
let leaf_nodes = res_trans_ie.leaf_nodes in
let (sil_e1', ie_typ) = extract_exp_from_list res_trans_ie.exps

@ -3,7 +3,7 @@ digraph iCFG {
5 -> 4 ;
4 [label="4: DeclStmt \n *&r:int =&v [line 12]\n NULLIFY(&r,false); [line 12]\n " shape="box"]
4 [label="4: DeclStmt \n *&r:int &=&v [line 12]\n NULLIFY(&r,false); [line 12]\n " shape="box"]
4 -> 3 ;

@ -3,7 +3,7 @@ digraph iCFG {
15 -> 14 ;
14 [label="14: DeclStmt \n n$1=*&par:int * [line 24]\n *&d:int =n$1 [line 24]\n REMOVE_TEMPS(n$1); [line 24]\n NULLIFY(&d,false); [line 24]\n " shape="box"]
14 [label="14: DeclStmt \n n$1=*&par:int * [line 24]\n *&d:int &=n$1 [line 24]\n REMOVE_TEMPS(n$1); [line 24]\n NULLIFY(&d,false); [line 24]\n " shape="box"]
14 -> 13 ;
@ -22,7 +22,7 @@ digraph iCFG {
10 -> 9 ;
9 [label="9: DeclStmt \n *&d:int =&par [line 18]\n NULLIFY(&d,false); [line 18]\n " shape="box"]
9 [label="9: DeclStmt \n *&d:int &=&par [line 18]\n NULLIFY(&d,false); [line 18]\n " shape="box"]
9 -> 8 ;
@ -41,7 +41,7 @@ digraph iCFG {
5 -> 4 ;
4 [label="4: DeclStmt \n n$1=*&par:int & [line 12]\n *&d:int =n$1 [line 12]\n REMOVE_TEMPS(n$1); [line 12]\n NULLIFY(&d,false); [line 12]\n " shape="box"]
4 [label="4: DeclStmt \n n$1=*&par:int & [line 12]\n *&d:int &=n$1 [line 12]\n REMOVE_TEMPS(n$1); [line 12]\n NULLIFY(&d,false); [line 12]\n " shape="box"]
4 -> 3 ;

@ -75,7 +75,7 @@ digraph iCFG {
98 -> 102 ;
97 [label="97: Call _fun_set_field_ref \n n$2=*&x:class X & [line 113]\n _fun_set_field_ref(n$2:class X ,1:int ) [line 113]\n REMOVE_TEMPS(n$2); [line 113]\n " shape="box"]
97 [label="97: Call _fun_set_field_ref \n n$2=*&x:class X & [line 113]\n _fun_set_field_ref(n$2:class X &,1:int ) [line 113]\n REMOVE_TEMPS(n$2); [line 113]\n " shape="box"]
97 -> 96 ;
@ -90,7 +90,7 @@ digraph iCFG {
94 -> 97 ;
93 [label="93: Call _fun_set_field_ref \n n$2=*&x:class X & [line 108]\n _fun_set_field_ref(n$2:class X ,0:int ) [line 108]\n REMOVE_TEMPS(n$2); [line 108]\n " shape="box"]
93 [label="93: Call _fun_set_field_ref \n n$2=*&x:class X & [line 108]\n _fun_set_field_ref(n$2:class X &,0:int ) [line 108]\n REMOVE_TEMPS(n$2); [line 108]\n " shape="box"]
93 -> 92 ;
@ -105,7 +105,7 @@ digraph iCFG {
90 -> 93 ;
89 [label="89: Call _fun_nonzero_ref \n n$2=*&x:class X & [line 103]\n _fun_nonzero_ref(n$2:class X ) [line 103]\n REMOVE_TEMPS(n$2); [line 103]\n " shape="box"]
89 [label="89: Call _fun_nonzero_ref \n n$2=*&x:class X & [line 103]\n _fun_nonzero_ref(n$2:class X &) [line 103]\n REMOVE_TEMPS(n$2); [line 103]\n " shape="box"]
89 -> 88 ;
@ -120,7 +120,7 @@ digraph iCFG {
86 -> 89 ;
85 [label="85: Call _fun_zero_ref \n n$2=*&x:class X & [line 98]\n _fun_zero_ref(n$2:class X ) [line 98]\n REMOVE_TEMPS(n$2); [line 98]\n " shape="box"]
85 [label="85: Call _fun_zero_ref \n n$2=*&x:class X & [line 98]\n _fun_zero_ref(n$2:class X &) [line 98]\n REMOVE_TEMPS(n$2); [line 98]\n " shape="box"]
85 -> 84 ;

@ -3,11 +3,11 @@ digraph iCFG {
40 -> 39 ;
39 [label="39: DeclStmt \n *&r:int =&a [line 48]\n " shape="box"]
39 [label="39: DeclStmt \n *&r:int &=&a [line 48]\n " shape="box"]
39 -> 38 ;
38 [label="38: Call _fun_zero_ref \n n$1=*&r:int & [line 49]\n _fun_zero_ref(n$1:int ) [line 49]\n REMOVE_TEMPS(n$1); [line 49]\n NULLIFY(&r,false); [line 49]\n " shape="box"]
38 [label="38: Call _fun_zero_ref \n n$1=*&r:int & [line 49]\n _fun_zero_ref(n$1:int &) [line 49]\n REMOVE_TEMPS(n$1); [line 49]\n NULLIFY(&r,false); [line 49]\n " shape="box"]
38 -> 37 ;
@ -26,7 +26,7 @@ digraph iCFG {
34 -> 33 ;
33 [label="33: Call _fun_zero_ref \n _fun_zero_ref(&a:int ) [line 42]\n " shape="box"]
33 [label="33: Call _fun_zero_ref \n _fun_zero_ref(&a:int &) [line 42]\n " shape="box"]
33 -> 32 ;
@ -45,7 +45,7 @@ digraph iCFG {
29 -> 28 ;
28 [label="28: DeclStmt \n *&r:int =&a [line 35]\n " shape="box"]
28 [label="28: DeclStmt \n *&r:int &=&a [line 35]\n " shape="box"]
28 -> 27 ;

@ -15,7 +15,7 @@ digraph iCFG {
20 -> 19 ;
19 [label="19: Call _fun_fun_r \n n$0=*&p:int * [line 33]\n n$1=_fun_fun_r(n$0:int ) [line 33]\n REMOVE_TEMPS(n$0,n$1); [line 33]\n NULLIFY(&p,false); [line 33]\n NULLIFY(&a,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"]
19 [label="19: Call _fun_fun_r \n n$0=*&p:int * [line 33]\n n$1=_fun_fun_r(n$0:int &) [line 33]\n REMOVE_TEMPS(n$0,n$1); [line 33]\n NULLIFY(&p,false); [line 33]\n NULLIFY(&a,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"]
19 -> 18 ;
@ -30,7 +30,7 @@ digraph iCFG {
16 -> 15 ;
15 [label="15: DeclStmt \n *&r:int =&a [line 19]\n " shape="box"]
15 [label="15: DeclStmt \n *&r:int &=&a [line 19]\n " shape="box"]
15 -> 14 ;
@ -42,7 +42,7 @@ digraph iCFG {
13 -> 12 ;
12 [label="12: Call _fun_fun_r \n n$0=*&r:int & [line 23]\n n$1=_fun_fun_r(n$0:int ) [line 23]\n REMOVE_TEMPS(n$0,n$1); [line 23]\n NULLIFY(&r,false); [line 23]\n NULLIFY(&a,false); [line 23]\n APPLY_ABSTRACTION; [line 23]\n " shape="box"]
12 [label="12: Call _fun_fun_r \n n$0=*&r:int & [line 23]\n n$1=_fun_fun_r(n$0:int &) [line 23]\n REMOVE_TEMPS(n$0,n$1); [line 23]\n NULLIFY(&r,false); [line 23]\n NULLIFY(&a,false); [line 23]\n APPLY_ABSTRACTION; [line 23]\n " shape="box"]
12 -> 11 ;

Loading…
Cancel
Save