Fix translation of passing struct parameters by value

Summary:
Pass object by reference every time struct object is passed by value
in C++. Do it only for C++/objC++ where we have guarantee that the
object which is passed will be temporary one (created by copy constructor).

Reviewed By: jberdine

Differential Revision: D3346271

fbshipit-source-id: d3e5daa
master
Andrzej Kotulski 9 years ago committed by Facebook Github Bot 0
parent 8639042bc0
commit 3699b9c0dc

@ -107,6 +107,8 @@ let create_struct_type struct_name = `StructType struct_name
let create_pointer_type typ = `PointerOf typ let create_pointer_type typ = `PointerOf typ
let create_reference_type typ = `ReferenceOf typ
let create_integer_literal n = let create_integer_literal n =
let stmt_info = dummy_stmt_info () in let stmt_info = dummy_stmt_info () in
let expr_info = { let expr_info = {

@ -45,6 +45,8 @@ val create_struct_type : string -> type_ptr
val create_pointer_type : type_ptr -> type_ptr val create_pointer_type : type_ptr -> type_ptr
val create_reference_type : type_ptr -> type_ptr
val make_objc_ivar_decl : decl_info -> type_ptr -> named_decl_info -> decl val make_objc_ivar_decl : decl_info -> type_ptr -> named_decl_info -> decl
val make_stmt_info : decl_info -> stmt_info val make_stmt_info : decl_info -> stmt_info

@ -110,7 +110,12 @@ let get_parameters tenv function_method_decl_info =
match par with match par with
| Clang_ast_t.ParmVarDecl (_, name_info, type_ptr, var_decl_info) -> | Clang_ast_t.ParmVarDecl (_, name_info, type_ptr, var_decl_info) ->
let name = General_utils.get_var_name_string name_info var_decl_info in let name = General_utils.get_var_name_string name_info var_decl_info in
(name, type_ptr) let param_typ = CTypes_decl.type_ptr_to_sil_type tenv type_ptr in
let type_ptr' = match param_typ with
| Sil.Tstruct _ when General_utils.is_cpp_translation Config.clang_lang ->
Ast_expressions.create_reference_type type_ptr
| _ -> type_ptr in
(name, type_ptr')
| _ -> assert false in | _ -> assert false in
let pars = IList.map par_to_ms_par (get_param_decls function_method_decl_info) in let pars = IList.map par_to_ms_par (get_param_decls function_method_decl_info) in
get_class_param function_method_decl_info @ pars @ get_return_param tenv function_method_decl_info get_class_param function_method_decl_info @ pars @ get_return_param tenv function_method_decl_info

@ -475,7 +475,13 @@ struct
let open CContext in let open CContext in
let context = trans_state.context in let context = trans_state.context in
let _, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in let _, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in
let typ = CTypes_decl.type_ptr_to_sil_type context.tenv type_ptr in let ast_typ = CTypes_decl.type_ptr_to_sil_type context.tenv type_ptr in
let typ = match ast_typ with
| Sil.Tstruct _ when decl_ref.Clang_ast_t.dr_kind = `ParmVar ->
if General_utils.is_cpp_translation Config.clang_lang then
Sil.Tptr (ast_typ, Sil.Pk_reference)
else ast_typ
| _ -> ast_typ in
let procname = Cfg.Procdesc.get_proc_name context.procdesc in let procname = Cfg.Procdesc.get_proc_name context.procdesc in
let sil_loc = CLocation.get_sil_location stmt_info context in let sil_loc = CLocation.get_sil_location stmt_info context in
let pvar = CVar_decl.sil_var_of_decl_ref context decl_ref procname in let pvar = CVar_decl.sil_var_of_decl_ref context decl_ref procname in
@ -492,10 +498,11 @@ struct
else [(e, typ)] in else [(e, typ)] in
Printing.log_out "\n\n PVAR ='%s'\n\n" (Pvar.to_string pvar); Printing.log_out "\n\n PVAR ='%s'\n\n" (Pvar.to_string pvar);
let res_trans = { empty_res_trans with exps = exps } in let res_trans = { empty_res_trans with exps = exps } in
if CTypes.is_reference_type type_ptr then match typ with
(* dereference pvar due to the behavior of reference types in clang's AST *) | Sil.Tptr (_, Sil.Pk_reference) ->
dereference_value_from_result sil_loc res_trans ~strip_pointer:true (* dereference pvar due to the behavior of reference types in clang's AST *)
else res_trans dereference_value_from_result sil_loc res_trans ~strip_pointer:true
| _ -> res_trans
let field_deref_trans trans_state stmt_info pre_trans_result decl_ref ~is_constructor_init = let field_deref_trans trans_state stmt_info pre_trans_result decl_ref ~is_constructor_init =
let open CContext in let open CContext in

@ -177,6 +177,9 @@ and type_ptr_to_sil_type translate_decl tenv type_ptr =
| `PointerOf typ -> | `PointerOf typ ->
let sil_typ = type_ptr_to_sil_type translate_decl tenv typ in let sil_typ = type_ptr_to_sil_type translate_decl tenv typ in
Sil.Tptr (sil_typ, Sil.Pk_pointer) Sil.Tptr (sil_typ, Sil.Pk_pointer)
| `ReferenceOf typ ->
let sil_typ = type_ptr_to_sil_type translate_decl tenv typ in
Sil.Tptr (sil_typ, Sil.Pk_reference)
| `ClassType (name, lang) -> | `ClassType (name, lang) ->
let kind = match lang with `OBJC -> Csu.Objc | `CPP -> Csu.CPP in let kind = match lang with `OBJC -> Csu.Objc | `CPP -> Csu.CPP in
Sil.Tvar (CTypes.mk_classname name kind) Sil.Tvar (CTypes.mk_classname name kind)

@ -23,6 +23,7 @@ type t_ptr = [
| `TPtr of int | `TPtr of int
| `Prebuilt of int | `Prebuilt of int
| `PointerOf of t_ptr | `PointerOf of t_ptr
| `ReferenceOf of t_ptr
| `ClassType of class_info | `ClassType of class_info
| `StructType of string | `StructType of string
| `DeclPtr of int | `DeclPtr of int
@ -39,6 +40,7 @@ let rec type_ptr_to_string type_ptr = match type_ptr with
| `TPtr raw -> "clang_ptr_" ^ (string_of_int raw) | `TPtr raw -> "clang_ptr_" ^ (string_of_int raw)
| `Prebuilt raw -> "prebuilt_" ^ (string_of_int raw) | `Prebuilt raw -> "prebuilt_" ^ (string_of_int raw)
| `PointerOf typ -> "pointer_of_" ^ type_ptr_to_string typ | `PointerOf typ -> "pointer_of_" ^ type_ptr_to_string typ
| `ReferenceOf typ -> "reference_of_" ^ type_ptr_to_string typ
| `ClassType (name, _) -> "class_name_" ^ name | `ClassType (name, _) -> "class_name_" ^ name
| `StructType name -> "struct_name_" ^ name | `StructType name -> "struct_name_" ^ name
| `DeclPtr raw -> "decl_ptr_" ^ (string_of_int raw) | `DeclPtr raw -> "decl_ptr_" ^ (string_of_int raw)

@ -10,14 +10,14 @@ digraph iCFG {
4 -> 6 ; 4 -> 6 ;
3 [label="3: Constructor Init \n n$0=*&this:class Person * [line 14]\n n$1=*&l.top:int [line 14]\n *n$0.age:int =n$1 [line 14]\n REMOVE_TEMPS(n$0,n$1); [line 14]\n NULLIFY(&l); [line 14]\n NULLIFY(&this); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"] 3 [label="3: Constructor Init \n n$0=*&this:class Person * [line 14]\n n$1=*&l:class Insets & [line 14]\n n$2=*n$1.top:int [line 14]\n *n$0.age:int =n$2 [line 14]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 14]\n NULLIFY(&l); [line 14]\n NULLIFY(&this); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"]
3 -> 2 ; 3 -> 2 ;
2 [label="2: Exit Person_Person \n " color=yellow style=filled] 2 [label="2: Exit Person_Person \n " color=yellow style=filled]
1 [label="1: Start Person_Person\nFormals: this:class Person * l:class Insets \nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled] 1 [label="1: Start Person_Person\nFormals: this:class Person * l:class Insets &\nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled]
1 -> 3 ; 1 -> 3 ;

@ -10,24 +10,24 @@ digraph iCFG {
9 -> 11 ; 9 -> 11 ;
8 [label="8: Prune (false branch) \n PRUNE(((n$3 != n$5) == 0), false); [line 15]\n REMOVE_TEMPS(n$3,n$5); [line 15]\n NULLIFY(&i); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"] 8 [label="8: Prune (false branch) \n PRUNE(((n$4 != n$7) == 0), false); [line 15]\n REMOVE_TEMPS(n$4,n$7); [line 15]\n NULLIFY(&i); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"]
8 -> 2 ; 8 -> 2 ;
7 [label="7: Prune (true branch) \n PRUNE(((n$3 != n$5) != 0), true); [line 15]\n REMOVE_TEMPS(n$3,n$5); [line 15]\n " shape="invhouse"] 7 [label="7: Prune (true branch) \n PRUNE(((n$4 != n$7) != 0), true); [line 15]\n REMOVE_TEMPS(n$4,n$7); [line 15]\n " shape="invhouse"]
7 -> 5 ; 7 -> 5 ;
6 [label="6: BinaryOperatorStmt: NE \n n$3=*&i:int * [line 15]\n n$4=*&list:class std::initializer_list<int> [line 15]\n n$5=_fun_std::initializer_list<int>_end(&list:class std::initializer_list<int> &) [line 15]\n REMOVE_TEMPS(n$4); [line 15]\n " shape="box"] 6 [label="6: BinaryOperatorStmt: NE \n n$4=*&i:int * [line 15]\n n$5=*&list:class std::initializer_list<int> & [line 15]\n n$6=*n$5:class std::initializer_list<int> [line 15]\n n$7=_fun_std::initializer_list<int>_end(n$5:class std::initializer_list<int> &) [line 15]\n REMOVE_TEMPS(n$5,n$6); [line 15]\n " shape="box"]
6 -> 7 ; 6 -> 7 ;
6 -> 8 ; 6 -> 8 ;
5 [label="5: UnaryOperator \n n$2=*&i:int * [line 15]\n *&i:int *=(n$2 + 1) [line 15]\n REMOVE_TEMPS(n$2); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] 5 [label="5: UnaryOperator \n n$3=*&i:int * [line 15]\n *&i:int *=(n$3 + 1) [line 15]\n REMOVE_TEMPS(n$3); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"]
5 -> 3 ; 5 -> 3 ;
4 [label="4: DeclStmt \n n$0=*&list:class std::initializer_list<int> [line 15]\n n$1=_fun_std::initializer_list<int>_begin(&list:class std::initializer_list<int> &) [line 15]\n *&i:int *=n$1 [line 15]\n REMOVE_TEMPS(n$0,n$1); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] 4 [label="4: DeclStmt \n n$0=*&list:class std::initializer_list<int> & [line 15]\n n$1=*n$0:class std::initializer_list<int> [line 15]\n n$2=_fun_std::initializer_list<int>_begin(n$0:class std::initializer_list<int> &) [line 15]\n *&i:int *=n$2 [line 15]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"]
4 -> 3 ; 4 -> 3 ;
@ -35,10 +35,10 @@ digraph iCFG {
3 -> 6 ; 3 -> 6 ;
2 [label="2: Exit X_X \n NULLIFY(&list); [line 18]\n " color=yellow style=filled] 2 [label="2: Exit X_X \n " color=yellow style=filled]
1 [label="1: Start X_X\nFormals: this:class X * list:class std::initializer_list<int> \nLocals: i:int * \n DECLARE_LOCALS(&return,&i); [line 14]\n " color=yellow style=filled] 1 [label="1: Start X_X\nFormals: this:class X * list:class std::initializer_list<int> &\nLocals: i:int * \n DECLARE_LOCALS(&return,&i); [line 14]\n " color=yellow style=filled]
1 -> 4 ; 1 -> 4 ;

@ -96,14 +96,14 @@ digraph iCFG {
19 -> 24 ; 19 -> 24 ;
18 [label="18: Return Stmt \n n$0=*&i1.val:int [line 21]\n n$1=*&i2.val:int [line 21]\n *&return:_Bool =(n$0 != n$1) [line 21]\n REMOVE_TEMPS(n$0,n$1); [line 21]\n NULLIFY(&i1); [line 21]\n NULLIFY(&i2); [line 21]\n APPLY_ABSTRACTION; [line 21]\n " shape="box"] 18 [label="18: Return Stmt \n n$0=*&i1:class iterator & [line 21]\n n$1=*n$0.val:int [line 21]\n n$2=*&i2:class iterator & [line 21]\n n$3=*n$2.val:int [line 21]\n *&return:_Bool =(n$1 != n$3) [line 21]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 21]\n NULLIFY(&i1); [line 21]\n NULLIFY(&i2); [line 21]\n APPLY_ABSTRACTION; [line 21]\n " shape="box"]
18 -> 17 ; 18 -> 17 ;
17 [label="17: Exit operator!= \n " color=yellow style=filled] 17 [label="17: Exit operator!= \n " color=yellow style=filled]
16 [label="16: Start operator!=\nFormals: i1:class iterator i2:class iterator \nLocals: \n DECLARE_LOCALS(&return); [line 21]\n " color=yellow style=filled] 16 [label="16: Start operator!=\nFormals: i1:class iterator & i2:class iterator &\nLocals: \n DECLARE_LOCALS(&return); [line 21]\n " color=yellow style=filled]
16 -> 18 ; 16 -> 18 ;

@ -18,18 +18,18 @@ digraph iCFG {
37 -> 41 ; 37 -> 41 ;
36 [label="36: BinaryOperatorStmt: Assign \n *&s.b1:int =1 [line 62]\n " shape="box"] 36 [label="36: BinaryOperatorStmt: Assign \n n$2=*&s:class Sub & [line 62]\n *n$2.b1:int =1 [line 62]\n REMOVE_TEMPS(n$2); [line 62]\n " shape="box"]
36 -> 35 ; 36 -> 35 ;
35 [label="35: Return Stmt \n n$0=*&s.b1:int [line 63]\n *&return:int =(1 / n$0) [line 63]\n REMOVE_TEMPS(n$0); [line 63]\n NULLIFY(&s); [line 63]\n APPLY_ABSTRACTION; [line 63]\n " shape="box"] 35 [label="35: Return Stmt \n n$0=*&s:class Sub & [line 63]\n n$1=*n$0.b1:int [line 63]\n *&return:int =(1 / n$1) [line 63]\n REMOVE_TEMPS(n$0,n$1); [line 63]\n NULLIFY(&s); [line 63]\n APPLY_ABSTRACTION; [line 63]\n " shape="box"]
35 -> 34 ; 35 -> 34 ;
34 [label="34: Exit div1_b1 \n " color=yellow style=filled] 34 [label="34: Exit div1_b1 \n " color=yellow style=filled]
33 [label="33: Start div1_b1\nFormals: s:class Sub \nLocals: \n DECLARE_LOCALS(&return); [line 61]\n " color=yellow style=filled] 33 [label="33: Start div1_b1\nFormals: s:class Sub &\nLocals: \n DECLARE_LOCALS(&return); [line 61]\n " color=yellow style=filled]
33 -> 36 ; 33 -> 36 ;
@ -71,11 +71,11 @@ digraph iCFG {
23 -> 27 ; 23 -> 27 ;
22 [label="22: BinaryOperatorStmt: Assign \n *&s.b1:int =0 [line 44]\n " shape="box"] 22 [label="22: BinaryOperatorStmt: Assign \n n$3=*&s:class Sub & [line 44]\n *n$3.b1:int =0 [line 44]\n REMOVE_TEMPS(n$3); [line 44]\n " shape="box"]
22 -> 21 ; 22 -> 21 ;
21 [label="21: DeclStmt \n *&b:class Sub &=&s [line 45]\n " shape="box"] 21 [label="21: DeclStmt \n n$2=*&s:class Sub & [line 45]\n *&b:class Sub &=n$2 [line 45]\n REMOVE_TEMPS(n$2); [line 45]\n NULLIFY(&s); [line 45]\n " shape="box"]
21 -> 20 ; 21 -> 20 ;
@ -83,10 +83,10 @@ digraph iCFG {
20 -> 19 ; 20 -> 19 ;
19 [label="19: Exit div0_cast_ref \n NULLIFY(&s); [line 47]\n " color=yellow style=filled] 19 [label="19: Exit div0_cast_ref \n " color=yellow style=filled]
18 [label="18: Start div0_cast_ref\nFormals: s:class Sub \nLocals: b:class Base1 & \n DECLARE_LOCALS(&return,&b); [line 43]\n " color=yellow style=filled] 18 [label="18: Start div0_cast_ref\nFormals: s:class Sub &\nLocals: b:class Base1 & \n DECLARE_LOCALS(&return,&b); [line 43]\n " color=yellow style=filled]
18 -> 22 ; 18 -> 22 ;
@ -109,48 +109,48 @@ digraph iCFG {
13 -> 17 ; 13 -> 17 ;
12 [label="12: BinaryOperatorStmt: Assign \n *&s.s:int =0 [line 33]\n " shape="box"] 12 [label="12: BinaryOperatorStmt: Assign \n n$2=*&s:class Sub & [line 33]\n *n$2.s:int =0 [line 33]\n REMOVE_TEMPS(n$2); [line 33]\n " shape="box"]
12 -> 11 ; 12 -> 11 ;
11 [label="11: Return Stmt \n n$0=*&s.s:int [line 34]\n *&return:int =(1 / n$0) [line 34]\n REMOVE_TEMPS(n$0); [line 34]\n NULLIFY(&s); [line 34]\n APPLY_ABSTRACTION; [line 34]\n " shape="box"] 11 [label="11: Return Stmt \n n$0=*&s:class Sub & [line 34]\n n$1=*n$0.s:int [line 34]\n *&return:int =(1 / n$1) [line 34]\n REMOVE_TEMPS(n$0,n$1); [line 34]\n NULLIFY(&s); [line 34]\n APPLY_ABSTRACTION; [line 34]\n " shape="box"]
11 -> 10 ; 11 -> 10 ;
10 [label="10: Exit div0_s \n " color=yellow style=filled] 10 [label="10: Exit div0_s \n " color=yellow style=filled]
9 [label="9: Start div0_s\nFormals: s:class Sub \nLocals: \n DECLARE_LOCALS(&return); [line 32]\n " color=yellow style=filled] 9 [label="9: Start div0_s\nFormals: s:class Sub &\nLocals: \n DECLARE_LOCALS(&return); [line 32]\n " color=yellow style=filled]
9 -> 12 ; 9 -> 12 ;
8 [label="8: BinaryOperatorStmt: Assign \n *&s.b2:int =0 [line 28]\n " shape="box"] 8 [label="8: BinaryOperatorStmt: Assign \n n$2=*&s:class Sub & [line 28]\n *n$2.b2:int =0 [line 28]\n REMOVE_TEMPS(n$2); [line 28]\n " shape="box"]
8 -> 7 ; 8 -> 7 ;
7 [label="7: Return Stmt \n n$0=*&s.b2:int [line 29]\n *&return:int =(1 / n$0) [line 29]\n REMOVE_TEMPS(n$0); [line 29]\n NULLIFY(&s); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] 7 [label="7: Return Stmt \n n$0=*&s:class Sub & [line 29]\n n$1=*n$0.b2:int [line 29]\n *&return:int =(1 / n$1) [line 29]\n REMOVE_TEMPS(n$0,n$1); [line 29]\n NULLIFY(&s); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"]
7 -> 6 ; 7 -> 6 ;
6 [label="6: Exit div0_b2 \n " color=yellow style=filled] 6 [label="6: Exit div0_b2 \n " color=yellow style=filled]
5 [label="5: Start div0_b2\nFormals: s:class Sub \nLocals: \n DECLARE_LOCALS(&return); [line 27]\n " color=yellow style=filled] 5 [label="5: Start div0_b2\nFormals: s:class Sub &\nLocals: \n DECLARE_LOCALS(&return); [line 27]\n " color=yellow style=filled]
5 -> 8 ; 5 -> 8 ;
4 [label="4: BinaryOperatorStmt: Assign \n *&s.b1:int =0 [line 23]\n " shape="box"] 4 [label="4: BinaryOperatorStmt: Assign \n n$2=*&s:class Sub & [line 23]\n *n$2.b1:int =0 [line 23]\n REMOVE_TEMPS(n$2); [line 23]\n " shape="box"]
4 -> 3 ; 4 -> 3 ;
3 [label="3: Return Stmt \n n$0=*&s.b1:int [line 24]\n *&return:int =(1 / n$0) [line 24]\n REMOVE_TEMPS(n$0); [line 24]\n NULLIFY(&s); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] 3 [label="3: Return Stmt \n n$0=*&s:class Sub & [line 24]\n n$1=*n$0.b1:int [line 24]\n *&return:int =(1 / n$1) [line 24]\n REMOVE_TEMPS(n$0,n$1); [line 24]\n NULLIFY(&s); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"]
3 -> 2 ; 3 -> 2 ;
2 [label="2: Exit div0_b1 \n " color=yellow style=filled] 2 [label="2: Exit div0_b1 \n " color=yellow style=filled]
1 [label="1: Start div0_b1\nFormals: s:class Sub \nLocals: \n DECLARE_LOCALS(&return); [line 22]\n " color=yellow style=filled] 1 [label="1: Start div0_b1\nFormals: s:class Sub &\nLocals: \n DECLARE_LOCALS(&return); [line 22]\n " color=yellow style=filled]
1 -> 4 ; 1 -> 4 ;

@ -0,0 +1,55 @@
/*
* 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.
*/
struct X {
int f;
X(int f) : f(f) {}
};
struct Y {
Y(const X& x) : x(x) {}
X x;
};
int get_f(X val) { return val.f; }
// val is passed by value, so it's not really a setter
void set_f(X val, int f) { val.f = f; }
int var_div0() {
X x(0);
return 1 / get_f(x);
}
int var_div1() {
X x(1);
return 1 / get_f(x);
}
int temp_div0() { return 1 / get_f(X(0)); }
int temp_div1() { return 1 / get_f(X(1)); }
int field_div0() {
X x(0);
Y y(x);
return 1 / get_f(y.x);
}
int param_get_copied_div0() {
X x(0);
set_f(x, 1); // this won't change x
return 1 / x.f;
}
int param_get_copied_div1() {
X x(1);
set_f(x, 0); // this won't change x
return 1 / x.f;
}

@ -0,0 +1,177 @@
digraph iCFG {
47 [label="47: DeclStmt \n _fun_X_X(&x:class X *,1:int ) [line 52]\n " shape="box"]
47 -> 46 ;
46 [label="46: Call _fun_set_f \n _fun_X_X(&__temp_construct_n$1:class X *,&x:class X &) [line 53]\n _fun_set_f(&__temp_construct_n$1:class X ,0:int ) [line 53]\n " shape="box"]
46 -> 45 ;
45 [label="45: Return Stmt \n n$0=*&x.f:int [line 54]\n *&return:int =(1 / n$0) [line 54]\n REMOVE_TEMPS(n$0); [line 54]\n APPLY_ABSTRACTION; [line 54]\n " shape="box"]
45 -> 44 ;
44 [label="44: Exit param_get_copied_div1 \n NULLIFY(&x); [line 55]\n NULLIFY(&__temp_construct_n$1); [line 55]\n " color=yellow style=filled]
43 [label="43: Start param_get_copied_div1\nFormals: \nLocals: __temp_construct_n$1:class X x:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$1,&x); [line 51]\n " color=yellow style=filled]
43 -> 47 ;
42 [label="42: DeclStmt \n _fun_X_X(&x:class X *,0:int ) [line 46]\n " shape="box"]
42 -> 41 ;
41 [label="41: Call _fun_set_f \n _fun_X_X(&__temp_construct_n$1:class X *,&x:class X &) [line 47]\n _fun_set_f(&__temp_construct_n$1:class X ,1:int ) [line 47]\n " shape="box"]
41 -> 40 ;
40 [label="40: Return Stmt \n n$0=*&x.f:int [line 48]\n *&return:int =(1 / n$0) [line 48]\n REMOVE_TEMPS(n$0); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"]
40 -> 39 ;
39 [label="39: Exit param_get_copied_div0 \n NULLIFY(&x); [line 49]\n NULLIFY(&__temp_construct_n$1); [line 49]\n " color=yellow style=filled]
38 [label="38: Start param_get_copied_div0\nFormals: \nLocals: __temp_construct_n$1:class X x:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$1,&x); [line 45]\n " color=yellow style=filled]
38 -> 42 ;
37 [label="37: DeclStmt \n _fun_X_X(&x:class X *,0:int ) [line 40]\n " shape="box"]
37 -> 36 ;
36 [label="36: DeclStmt \n _fun_Y_Y(&y:class Y *,&x:class X &) [line 41]\n " shape="box"]
36 -> 35 ;
35 [label="35: Return Stmt \n _fun_X_X(&__temp_construct_n$0:class X *,&y.x:class X &) [line 42]\n n$1=_fun_get_f(&__temp_construct_n$0:class X ) [line 42]\n *&return:int =(1 / n$1) [line 42]\n REMOVE_TEMPS(n$1); [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"]
35 -> 34 ;
34 [label="34: Exit field_div0 \n NULLIFY(&y); [line 43]\n NULLIFY(&x); [line 43]\n NULLIFY(&__temp_construct_n$0); [line 43]\n " color=yellow style=filled]
33 [label="33: Start field_div0\nFormals: \nLocals: __temp_construct_n$0:class X y:class Y x:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$0,&y,&x); [line 39]\n " color=yellow style=filled]
33 -> 37 ;
32 [label="32: Return Stmt \n _fun_X_X(&SIL_materialize_temp__n$1:class X *,1:int ) [line 37]\n _fun_X_X(&__temp_construct_n$0:class X *,&SIL_materialize_temp__n$1:class X &) [line 37]\n n$2=_fun_get_f(&__temp_construct_n$0:class X ) [line 37]\n *&return:int =(1 / n$2) [line 37]\n REMOVE_TEMPS(n$2); [line 37]\n APPLY_ABSTRACTION; [line 37]\n " shape="box"]
32 -> 31 ;
31 [label="31: Exit temp_div1 \n NULLIFY(&__temp_construct_n$0); [line 37]\n NULLIFY(&SIL_materialize_temp__n$1); [line 37]\n " color=yellow style=filled]
30 [label="30: Start temp_div1\nFormals: \nLocals: __temp_construct_n$0:class X SIL_materialize_temp__n$1:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$0,&SIL_materialize_temp__n$1); [line 37]\n " color=yellow style=filled]
30 -> 32 ;
29 [label="29: Return Stmt \n _fun_X_X(&SIL_materialize_temp__n$1:class X *,0:int ) [line 35]\n _fun_X_X(&__temp_construct_n$0:class X *,&SIL_materialize_temp__n$1:class X &) [line 35]\n n$2=_fun_get_f(&__temp_construct_n$0:class X ) [line 35]\n *&return:int =(1 / n$2) [line 35]\n REMOVE_TEMPS(n$2); [line 35]\n APPLY_ABSTRACTION; [line 35]\n " shape="box"]
29 -> 28 ;
28 [label="28: Exit temp_div0 \n NULLIFY(&__temp_construct_n$0); [line 35]\n NULLIFY(&SIL_materialize_temp__n$1); [line 35]\n " color=yellow style=filled]
27 [label="27: Start temp_div0\nFormals: \nLocals: __temp_construct_n$0:class X SIL_materialize_temp__n$1:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$0,&SIL_materialize_temp__n$1); [line 35]\n " color=yellow style=filled]
27 -> 29 ;
26 [label="26: DeclStmt \n _fun_X_X(&x:class X *,1:int ) [line 31]\n " shape="box"]
26 -> 25 ;
25 [label="25: Return Stmt \n _fun_X_X(&__temp_construct_n$0:class X *,&x:class X &) [line 32]\n n$1=_fun_get_f(&__temp_construct_n$0:class X ) [line 32]\n *&return:int =(1 / n$1) [line 32]\n REMOVE_TEMPS(n$1); [line 32]\n APPLY_ABSTRACTION; [line 32]\n " shape="box"]
25 -> 24 ;
24 [label="24: Exit var_div1 \n NULLIFY(&x); [line 33]\n NULLIFY(&__temp_construct_n$0); [line 33]\n " color=yellow style=filled]
23 [label="23: Start var_div1\nFormals: \nLocals: __temp_construct_n$0:class X x:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$0,&x); [line 30]\n " color=yellow style=filled]
23 -> 26 ;
22 [label="22: DeclStmt \n _fun_X_X(&x:class X *,0:int ) [line 26]\n " shape="box"]
22 -> 21 ;
21 [label="21: Return Stmt \n _fun_X_X(&__temp_construct_n$0:class X *,&x:class X &) [line 27]\n n$1=_fun_get_f(&__temp_construct_n$0:class X ) [line 27]\n *&return:int =(1 / n$1) [line 27]\n REMOVE_TEMPS(n$1); [line 27]\n APPLY_ABSTRACTION; [line 27]\n " shape="box"]
21 -> 20 ;
20 [label="20: Exit var_div0 \n NULLIFY(&x); [line 28]\n NULLIFY(&__temp_construct_n$0); [line 28]\n " color=yellow style=filled]
19 [label="19: Start var_div0\nFormals: \nLocals: __temp_construct_n$0:class X x:class X \n DECLARE_LOCALS(&return,&__temp_construct_n$0,&x); [line 25]\n " color=yellow style=filled]
19 -> 22 ;
18 [label="18: BinaryOperatorStmt: Assign \n n$0=*&val:class X & [line 23]\n n$1=*&f:int [line 23]\n *n$0.f:int =n$1 [line 23]\n REMOVE_TEMPS(n$0,n$1); [line 23]\n NULLIFY(&f); [line 23]\n NULLIFY(&val); [line 23]\n APPLY_ABSTRACTION; [line 23]\n " shape="box"]
18 -> 17 ;
17 [label="17: Exit set_f \n " color=yellow style=filled]
16 [label="16: Start set_f\nFormals: val:class X & f:int \nLocals: \n DECLARE_LOCALS(&return); [line 23]\n " color=yellow style=filled]
16 -> 18 ;
15 [label="15: Return Stmt \n n$0=*&val:class X & [line 20]\n n$1=*n$0.f:int [line 20]\n *&return:int =n$1 [line 20]\n REMOVE_TEMPS(n$0,n$1); [line 20]\n NULLIFY(&val); [line 20]\n APPLY_ABSTRACTION; [line 20]\n " shape="box"]
15 -> 14 ;
14 [label="14: Exit get_f \n " color=yellow style=filled]
13 [label="13: Start get_f\nFormals: val:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 20]\n " color=yellow style=filled]
13 -> 15 ;
12 [label="12: Constructor Init \n n$0=*&this:class Y * [line 16]\n n$1=*&x:class X & [line 16]\n _fun_X_X(n$0.x:class X *,n$1:class X &) [line 16]\n REMOVE_TEMPS(n$0,n$1); [line 16]\n NULLIFY(&this); [line 16]\n NULLIFY(&x); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
12 -> 11 ;
11 [label="11: Exit Y_Y \n " color=yellow style=filled]
10 [label="10: Start Y_Y\nFormals: this:class Y * x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 16]\n " color=yellow style=filled]
10 -> 12 ;
9 [label="9: Constructor Init \n n$0=*&this:class X * [line 10]\n n$1=*&__param_0:class X & [line 10]\n n$2=*n$1.f:int [line 10]\n *n$0.f:int =n$2 [line 10]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 10]\n NULLIFY(&__param_0); [line 10]\n NULLIFY(&this); [line 10]\n APPLY_ABSTRACTION; [line 10]\n " shape="box"]
9 -> 8 ;
8 [label="8: Exit X_X \n " color=yellow style=filled]
7 [label="7: Start X_X\nFormals: this:class X * __param_0:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 10]\n " color=yellow style=filled]
7 -> 9 ;
6 [label="6: Constructor Init \n n$0=*&this:class X * [line 10]\n n$1=*&__param_0:class X & [line 10]\n n$2=*n$1.f:int [line 10]\n *n$0.f:int =n$2 [line 10]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 10]\n NULLIFY(&__param_0); [line 10]\n NULLIFY(&this); [line 10]\n APPLY_ABSTRACTION; [line 10]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit X_X \n " color=yellow style=filled]
4 [label="4: Start X_X\nFormals: this:class X * __param_0:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 10]\n " color=yellow style=filled]
4 -> 6 ;
3 [label="3: Constructor Init \n n$0=*&this:class X * [line 12]\n n$1=*&f:int [line 12]\n *n$0.f:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&f); [line 12]\n NULLIFY(&this); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit X_X \n " color=yellow style=filled]
1 [label="1: Start X_X\nFormals: this:class X * f:int \nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,66 @@
/*
* 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 StructPassByValueTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/frontend/types/struct_pass_by_value.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 = {
"var_div0",
"temp_div0",
"field_div0",
"param_get_copied_div0",
};
assertThat(
"Results should contain the expected divide by zero",
inferResults,
containsExactly(
DIVIDE_BY_ZERO,
FILE,
procedures
)
);
}
}

@ -34,4 +34,10 @@ public class TypesTest {
throws InterruptedException, IOException, InferException { throws InterruptedException, IOException, InferException {
frontendTest("typeid_expr.cpp"); frontendTest("typeid_expr.cpp");
} }
@Test
public void structPassByValueDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("struct_pass_by_value.cpp");
}
} }

Loading…
Cancel
Save