diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index f8c9d9dc9..a29356220 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -296,7 +296,9 @@ struct Printing.log_out " priority node free = '%s'\n@." (string_of_bool (PriorityNode.is_priority_free trans_state)); let context = trans_state.context in - let tp = expr_info.Clang_ast_t.ei_type_ptr in + let pln = trans_state.parent_line_number in + let sil_loc = CLocation.get_sil_location stmt_info pln context in + let tp = get_type_decl_ref_exp_info decl_ref_expr_info in let typ = CTypes_decl.type_ptr_to_sil_type context.tenv tp in let name = get_name_decl_ref_exp_info decl_ref_expr_info stmt_info in let procname = Cfg.Procdesc.get_proc_name context.procdesc in @@ -355,7 +357,11 @@ struct [(e, typ)] else [(e, typ)] in Printing.log_out "\n\n PVAR ='%s'\n\n" (Sil.pvar_to_string pvar); - { empty_res_trans with exps = exps } + let res_trans = { empty_res_trans with exps = exps } in + if CTypes.is_reference_type tp then + (* dereference pvar due to the behavior of reference types in clang's AST *) + dereference_value_from_result sil_loc res_trans + else res_trans | _ -> let print_error decl_kind = Printing.log_stats @@ -366,7 +372,6 @@ struct | `CXXMethod -> print_error decl_kind; assert false | _ -> print_error decl_kind; assert false - let cxxThisExpr_trans trans_state stmt_info expr_info = let context = trans_state.context in let pln = trans_state.parent_line_number in @@ -379,10 +384,7 @@ struct let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv tp in let exps = [(exp, typ)] in (* there is no cast operation in AST, but backend needs it *) - let cast_kind = `LValueToRValue in - let cast_ids, cast_inst, cast_exp = cast_operation context cast_kind exps - (* unused *) typ sil_loc (* is_objc_bridged *) false in - { empty_res_trans with ids = cast_ids; instrs = cast_inst; exps = [(cast_exp, typ)] } + dereference_value_from_result sil_loc { empty_res_trans with exps = exps } let rec labelStmt_trans trans_state stmt_info stmt_list label_name = (* go ahead with the translation *) diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index 00af5f767..2603c41c8 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -358,6 +358,24 @@ let builtin_trans trans_state loc stmt_info function_type callee_pname_opt = Some (alloc_trans trans_state loc stmt_info function_type false) else None +let dereference_var_sil (exp, typ) sil_loc = + let id = Ident.create_fresh Ident.knormal in + let sil_instr = Sil.Letderef (id, exp, typ, sil_loc) in + ([id], [sil_instr], Sil.Var id) + +(** Given trans_result with ONE expression, create temporary variable with *) +(** value of an expression assigned to it *) +let dereference_value_from_result sil_loc trans_result = + let (obj_sil, class_typ) = extract_exp_from_list trans_result.exps "" in + let cast_ids, cast_inst, cast_exp = dereference_var_sil (obj_sil, class_typ) sil_loc in + let typ_no_ptr = match class_typ with | Sil.Tptr (typ, _) -> typ | _ -> assert false in + { trans_result with + ids = trans_result.ids @ cast_ids; + instrs = trans_result.instrs @ cast_inst; + exps = [(cast_exp, typ_no_ptr)] + } + + let cast_operation context cast_kind exps cast_typ sil_loc is_objc_bridged = let (exp, typ) = extract_exp_from_list exps "" in if is_objc_bridged then @@ -373,9 +391,7 @@ let cast_operation context cast_kind exps cast_typ sil_loc is_objc_bridged = | `LValueToRValue -> (* Takes an LValue and allow it to use it as RValue. *) (* So we assign the LValue to a temp and we pass it to the parent.*) - let id = Ident.create_fresh Ident.knormal in - let sil_instr = [Sil.Letderef (id, exp, typ, sil_loc)] in - ([id], sil_instr, Sil.Var id) + dereference_var_sil (exp, typ) sil_loc | `CPointerToObjCPointerCast -> ([], [], Sil.Cast(typ, exp)) | _ -> @@ -451,6 +467,13 @@ let get_name_decl_ref_exp_info decl_ref_expr_info si = (Clang_ast_j.string_of_decl_ref_expr_info decl_ref_expr_info ) (Clang_ast_j.string_of_stmt_info si); assert false +let get_type_decl_ref_exp_info decl_ref_expr_info = + match decl_ref_expr_info.Clang_ast_t.drti_decl_ref with + | Some d -> (match d.Clang_ast_t.dr_type_ptr with + | Some ptr -> ptr + | _ -> assert false) + | _ -> assert false + let is_superinstance mei = match mei.Clang_ast_t.omei_receiver_kind with | `SuperInstance -> true diff --git a/infer/src/clang/cTrans_utils.mli b/infer/src/clang/cTrans_utils.mli index d8c5fe2cf..1c95e96bd 100644 --- a/infer/src/clang/cTrans_utils.mli +++ b/infer/src/clang/cTrans_utils.mli @@ -71,6 +71,8 @@ val compute_instr_ids_exp_to_parent : val get_name_decl_ref_exp_info : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.stmt_info -> string +val get_type_decl_ref_exp_info : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.type_ptr + val get_decl_kind : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.decl_kind val get_decl_pointer : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.pointer @@ -81,6 +83,10 @@ val is_member_exp : Clang_ast_t.stmt -> bool val get_type_from_exp_stmt : Clang_ast_t.stmt -> Clang_ast_t.type_ptr +(** Given trans_result with ONE expression, create temporary variable with *) +(** dereferenced value of an expression assigned to it *) +val dereference_value_from_result : Location.t -> trans_result -> trans_result + val cast_operation : CContext.t -> Clang_ast_t.cast_kind -> (Sil.exp * Sil.typ) list -> Sil.typ -> Location.t -> bool -> Ident.t list * Sil.instr list * Sil.exp diff --git a/infer/src/clang/cTypes.ml b/infer/src/clang/cTypes.ml index 4f3df9d7b..63b8382d3 100644 --- a/infer/src/clang/cTypes.ml +++ b/infer/src/clang/cTypes.ml @@ -104,6 +104,11 @@ let is_block_type tp = | Some BlockPointerType _ -> true | _ -> false +let is_reference_type tp = + match Ast_utils.get_desugared_type tp with + | Some Clang_ast_t.LValueReferenceType _ -> true + | _ -> false + (* Expand a named type Tvar if it has a definition in tenv. This is used for Tenum, Tstruct, etc. *) let rec expand_structured_type tenv typ = match typ with diff --git a/infer/src/clang/cTypes.mli b/infer/src/clang/cTypes.mli index 85b06ea9f..d78bb2ca2 100644 --- a/infer/src/clang/cTypes.mli +++ b/infer/src/clang/cTypes.mli @@ -31,6 +31,8 @@ val return_type_of_function_type : Clang_ast_t.type_ptr -> Clang_ast_t.type_ptr val is_block_type : Clang_ast_t.type_ptr -> bool +val is_reference_type : Clang_ast_t.type_ptr -> bool + val expand_structured_type : Sil.tenv -> Sil.typ -> Sil.typ val get_name_from_type_pointer : string -> string * string diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/box.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/box.cpp new file mode 100644 index 000000000..001e9cc6a --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/box.cpp @@ -0,0 +1,14 @@ +/* +* Copyright (c) 2015 - 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. +*/ + +void test() { + int v = 3; + int& r = v; + int* p = &v; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/box.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/box.cpp.dot new file mode 100644 index 000000000..d11258665 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/box.cpp.dot @@ -0,0 +1,21 @@ +digraph iCFG { +5 [label="5: DeclStmt \n *&v:int =3 [line 11]\n " shape="box"] + + + 5 -> 4 ; +4 [label="4: DeclStmt \n *&r:int =&v [line 12]\n NULLIFY(&r,false); [line 12]\n " shape="box"] + + + 4 -> 3 ; +3 [label="3: DeclStmt \n *&p:int *=&v [line 13]\n NULLIFY(&p,false); [line 13]\n NULLIFY(&v,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit test \n " color=yellow style=filled] + + +1 [label="1: Start test\nFormals: \nLocals: p:int * r:int & v:int \n DECLARE_LOCALS(&return,&p,&r,&v); [line 10]\n NULLIFY(&p,false); [line 10]\n NULLIFY(&r,false); [line 10]\n " color=yellow style=filled] + + + 1 -> 5 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/init.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/init.cpp new file mode 100644 index 000000000..352adf05b --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/init.cpp @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2015 - 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. +*/ + +void init_from_ref(int &par) { + int v = par; + int& d = par; + int* p = ∥ +} + +void init_from_val(int par) { + int v = par; + int& d = par; + int* p = ∥ +} + +void init_from_ptr(int *par) { + int v = *par; + int& d = *par; + int* p = par; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/init.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/init.cpp.dot new file mode 100644 index 000000000..0278b46ee --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/init.cpp.dot @@ -0,0 +1,59 @@ +digraph iCFG { +15 [label="15: DeclStmt \n n$2=*&par:int * [line 23]\n n$3=*n$2:int [line 23]\n *&v:int =n$3 [line 23]\n REMOVE_TEMPS(n$2,n$3); [line 23]\n NULLIFY(&v,false); [line 23]\n " shape="box"] + + + 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 -> 13 ; +13 [label="13: DeclStmt \n n$0=*&par:int * [line 25]\n *&p:int *=n$0 [line 25]\n REMOVE_TEMPS(n$0); [line 25]\n NULLIFY(&p,false); [line 25]\n NULLIFY(&par,false); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"] + + + 13 -> 12 ; +12 [label="12: Exit init_from_ptr \n " color=yellow style=filled] + + +11 [label="11: Start init_from_ptr\nFormals: par:int *\nLocals: p:int * d:int & v:int \n DECLARE_LOCALS(&return,&p,&d,&v); [line 22]\n NULLIFY(&d,false); [line 22]\n NULLIFY(&p,false); [line 22]\n NULLIFY(&v,false); [line 22]\n " color=yellow style=filled] + + + 11 -> 15 ; +10 [label="10: DeclStmt \n n$0=*&par:int [line 17]\n *&v:int =n$0 [line 17]\n REMOVE_TEMPS(n$0); [line 17]\n NULLIFY(&v,false); [line 17]\n " shape="box"] + + + 10 -> 9 ; +9 [label="9: DeclStmt \n *&d:int =&par [line 18]\n NULLIFY(&d,false); [line 18]\n " shape="box"] + + + 9 -> 8 ; +8 [label="8: DeclStmt \n *&p:int *=&par [line 19]\n NULLIFY(&p,false); [line 19]\n NULLIFY(&par,false); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"] + + + 8 -> 7 ; +7 [label="7: Exit init_from_val \n " color=yellow style=filled] + + +6 [label="6: Start init_from_val\nFormals: par:int \nLocals: p:int * d:int & v:int \n DECLARE_LOCALS(&return,&p,&d,&v); [line 16]\n NULLIFY(&d,false); [line 16]\n NULLIFY(&p,false); [line 16]\n NULLIFY(&v,false); [line 16]\n " color=yellow style=filled] + + + 6 -> 10 ; +5 [label="5: DeclStmt \n n$2=*&par:int & [line 11]\n n$3=*n$2:int [line 11]\n *&v:int =n$3 [line 11]\n REMOVE_TEMPS(n$2,n$3); [line 11]\n NULLIFY(&v,false); [line 11]\n " shape="box"] + + + 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 -> 3 ; +3 [label="3: DeclStmt \n n$0=*&par:int & [line 13]\n *&p:int *=n$0 [line 13]\n REMOVE_TEMPS(n$0); [line 13]\n NULLIFY(&p,false); [line 13]\n NULLIFY(&par,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit init_from_ref \n " color=yellow style=filled] + + +1 [label="1: Start init_from_ref\nFormals: par:int &\nLocals: p:int * d:int & v:int \n DECLARE_LOCALS(&return,&p,&d,&v); [line 10]\n NULLIFY(&d,false); [line 10]\n NULLIFY(&p,false); [line 10]\n NULLIFY(&v,false); [line 10]\n " color=yellow style=filled] + + + 1 -> 5 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/member_access.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access.cpp new file mode 100644 index 000000000..907663962 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access.cpp @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2015 - 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; + int call() {return f;} +}; + +void access_ref(X& x) { + int f = x.f; + int c = x.call(); +} + +void access_ptr(X* x) { + int f = x->f; + int c = x->call(); +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/member_access.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access.cpp.dot new file mode 100644 index 000000000..f1a2f797e --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access.cpp.dot @@ -0,0 +1,43 @@ +digraph iCFG { +11 [label="11: DeclStmt \n n$2=*&x:class X * [line 21]\n n$3=*n$2.f:int [line 21]\n *&f:int =n$3 [line 21]\n REMOVE_TEMPS(n$2,n$3); [line 21]\n NULLIFY(&f,false); [line 21]\n " shape="box"] + + + 11 -> 10 ; +10 [label="10: DeclStmt \n n$0=*&x:class X * [line 22]\n n$1=_fun_X_call(n$0:class X ) [line 22]\n *&c:int =n$1 [line 22]\n REMOVE_TEMPS(n$0,n$1); [line 22]\n NULLIFY(&c,false); [line 22]\n NULLIFY(&x,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"] + + + 10 -> 9 ; +9 [label="9: Exit access_ptr \n " color=yellow style=filled] + + +8 [label="8: Start access_ptr\nFormals: x:class X *\nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 20]\n NULLIFY(&c,false); [line 20]\n NULLIFY(&f,false); [line 20]\n " color=yellow style=filled] + + + 8 -> 11 ; +7 [label="7: DeclStmt \n n$2=*&x:class X & [line 16]\n n$3=*n$2.f:int [line 16]\n *&f:int =n$3 [line 16]\n REMOVE_TEMPS(n$2,n$3); [line 16]\n NULLIFY(&f,false); [line 16]\n " shape="box"] + + + 7 -> 6 ; +6 [label="6: DeclStmt \n n$0=*&x:class X & [line 17]\n n$1=_fun_X_call(n$0:class X ) [line 17]\n *&c:int =n$1 [line 17]\n REMOVE_TEMPS(n$0,n$1); [line 17]\n NULLIFY(&c,false); [line 17]\n NULLIFY(&x,false); [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit access_ref \n " color=yellow style=filled] + + +4 [label="4: Start access_ref\nFormals: x:class X &\nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 15]\n NULLIFY(&c,false); [line 15]\n NULLIFY(&f,false); [line 15]\n " color=yellow style=filled] + + + 4 -> 7 ; +3 [label="3: Return Stmt \n n$0=*&this:class X * [line 12]\n n$1=*n$0.f:int [line 12]\n *&return:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit X_call \n " color=yellow style=filled] + + +1 [label="1: Start X_call\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/member_access_from_return.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access_from_return.cpp new file mode 100644 index 000000000..4f1e61521 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access_from_return.cpp @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2015 - 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; + int call() {return f;} +}; + +X global; +X * get_ptr() {return &global;} +X& get_ref() {return global;} + +void test_ref() { + int f = get_ref().f; + int c = get_ref().call(); +} + +void test_ptr() { + int f = get_ptr()->f; + int c = get_ptr()->call(); +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/member_access_from_return.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access_from_return.cpp.dot new file mode 100644 index 000000000..a13ebee02 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/member_access_from_return.cpp.dot @@ -0,0 +1,65 @@ +digraph iCFG { +17 [label="17: DeclStmt \n n$2=_fun_get_ptr() [line 25]\n n$3=*n$2.f:int [line 25]\n *&f:int =n$3 [line 25]\n REMOVE_TEMPS(n$2,n$3); [line 25]\n NULLIFY(&f,false); [line 25]\n " shape="box"] + + + 17 -> 16 ; +16 [label="16: DeclStmt \n n$0=_fun_get_ptr() [line 26]\n n$1=_fun_X_call(n$0:class X ) [line 26]\n *&c:int =n$1 [line 26]\n REMOVE_TEMPS(n$0,n$1); [line 26]\n NULLIFY(&c,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"] + + + 16 -> 15 ; +15 [label="15: Exit test_ptr \n " color=yellow style=filled] + + +14 [label="14: Start test_ptr\nFormals: \nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 24]\n NULLIFY(&c,false); [line 24]\n NULLIFY(&f,false); [line 24]\n " color=yellow style=filled] + + + 14 -> 17 ; +13 [label="13: DeclStmt \n n$2=_fun_get_ref() [line 20]\n n$3=*n$2.f:int [line 20]\n *&f:int =n$3 [line 20]\n REMOVE_TEMPS(n$2,n$3); [line 20]\n NULLIFY(&f,false); [line 20]\n " shape="box"] + + + 13 -> 12 ; +12 [label="12: DeclStmt \n n$0=_fun_get_ref() [line 21]\n n$1=_fun_X_call(n$0:class X ) [line 21]\n *&c:int =n$1 [line 21]\n REMOVE_TEMPS(n$0,n$1); [line 21]\n NULLIFY(&c,false); [line 21]\n APPLY_ABSTRACTION; [line 21]\n " shape="box"] + + + 12 -> 11 ; +11 [label="11: Exit test_ref \n " color=yellow style=filled] + + +10 [label="10: Start test_ref\nFormals: \nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 19]\n NULLIFY(&c,false); [line 19]\n NULLIFY(&f,false); [line 19]\n " color=yellow style=filled] + + + 10 -> 13 ; +9 [label="9: Return Stmt \n *&return:class X &=&#GB$global [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"] + + + 9 -> 8 ; +8 [label="8: Exit get_ref \n " color=yellow style=filled] + + +7 [label="7: Start get_ref\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 17]\n " color=yellow style=filled] + + + 7 -> 9 ; +6 [label="6: Return Stmt \n *&return:class X *=&#GB$global [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit get_ptr \n " color=yellow style=filled] + + +4 [label="4: Start get_ptr\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 16]\n " color=yellow style=filled] + + + 4 -> 6 ; +3 [label="3: Return Stmt \n n$0=*&this:class X * [line 12]\n n$1=*n$0.f:int [line 12]\n *&return:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit X_call \n " color=yellow style=filled] + + +1 [label="1: Start X_call\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp new file mode 100644 index 000000000..29f7035ef --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp @@ -0,0 +1,139 @@ +/* +* Copyright (c) 2015 - 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; + void nonzero() { f = 1; } + void zero() { f = 0; } + int div() { return 1/f; } +}; + +void zero_ptr(X *x) { + x->zero(); +} + +void nonzero_ptr(X *x) { + x->nonzero(); +} + +void set_field_ptr(X *x, int val) { + x->f = val; +} + +void zero_ref(X &x) { + x.zero(); +} + +void nonzero_ref(X &x) { + x.nonzero(); +} + +void set_field_ref(X &x, int val) { + x.f = val; +} + +X global; +X* get_global_ptr() { return &global;} +X& get_global_ref() { return global;} + +int method_div0_ptr(X *x) { + if (x) { + zero_ptr(x); + return x->div(); + } +} + +int method_div1_ptr(X *x) { + if (x) { + nonzero_ptr(x); + return x->div(); + } +} + +int field_div0_ptr(X *x) { + if(x) { + set_field_ptr(x, 0); + return x->div(); + } +} + +int field_div1_ptr(X *x) { + if(x) { + set_field_ptr(x, 1); + return x->div(); + } +} + +int get_global_ptr_div0_method() { + get_global_ptr()->f = 1; + get_global_ptr()->zero(); + get_global_ptr()->div(); +} + +int get_global_ptr_div1_method() { + get_global_ptr()->f = 0; + get_global_ptr()->nonzero(); + get_global_ptr()->div(); +} + +int get_global_ptr_div0_field() { + get_global_ptr()->nonzero(); + get_global_ptr()->f = 0; + get_global_ptr()->div(); +} + +int get_global_ptr_div1_field() { + get_global_ptr()->zero(); + get_global_ptr()->f = 1; + get_global_ptr()->div(); +} + +int method_div0_ref(X &x) { + zero_ref(x); + return x.div(); +} + +int method_div1_ref(X &x) { + nonzero_ref(x); + return x.div(); +} + +int field_div0_ref(X &x) { + set_field_ref(x, 0); + return x.div(); +} + +int field_div1_ref(X &x) { + set_field_ref(x, 1); + return x.div(); +} + +int get_global_ref_div0_method() { + get_global_ref().f = 1; + get_global_ref().zero(); + get_global_ref().div(); +} + +int get_global_ref_div1_method() { + get_global_ref().f = 0; + get_global_ref().nonzero(); + get_global_ref().div(); +} + +int get_global_ref_div0_field() { + get_global_ref().nonzero(); + get_global_ref().f = 0; + get_global_ref().div(); +} + +int get_global_ref_div1_field() { + get_global_ref().zero(); + get_global_ref().f = 1; + get_global_ref().div(); +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp.dot new file mode 100644 index 000000000..cf1e78788 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp.dot @@ -0,0 +1,447 @@ +digraph iCFG { +117 [label="117: Call _fun_X_zero \n n$3=_fun_get_global_ref() [line 136]\n _fun_X_zero(n$3:class X ) [line 136]\n REMOVE_TEMPS(n$3); [line 136]\n " shape="box"] + + + 117 -> 116 ; +116 [label="116: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ref() [line 137]\n *n$2.f:int =1 [line 137]\n REMOVE_TEMPS(n$2); [line 137]\n " shape="box"] + + + 116 -> 115 ; +115 [label="115: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 138]\n n$1=_fun_X_div(n$0:class X ) [line 138]\n REMOVE_TEMPS(n$0,n$1); [line 138]\n APPLY_ABSTRACTION; [line 138]\n " shape="box"] + + + 115 -> 114 ; +114 [label="114: Exit get_global_ref_div1_field \n " color=yellow style=filled] + + +113 [label="113: Start get_global_ref_div1_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 135]\n " color=yellow style=filled] + + + 113 -> 117 ; +112 [label="112: Call _fun_X_nonzero \n n$3=_fun_get_global_ref() [line 130]\n _fun_X_nonzero(n$3:class X ) [line 130]\n REMOVE_TEMPS(n$3); [line 130]\n " shape="box"] + + + 112 -> 111 ; +111 [label="111: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ref() [line 131]\n *n$2.f:int =0 [line 131]\n REMOVE_TEMPS(n$2); [line 131]\n " shape="box"] + + + 111 -> 110 ; +110 [label="110: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 132]\n n$1=_fun_X_div(n$0:class X ) [line 132]\n REMOVE_TEMPS(n$0,n$1); [line 132]\n APPLY_ABSTRACTION; [line 132]\n " shape="box"] + + + 110 -> 109 ; +109 [label="109: Exit get_global_ref_div0_field \n " color=yellow style=filled] + + +108 [label="108: Start get_global_ref_div0_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 129]\n " color=yellow style=filled] + + + 108 -> 112 ; +107 [label="107: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ref() [line 124]\n *n$3.f:int =0 [line 124]\n REMOVE_TEMPS(n$3); [line 124]\n " shape="box"] + + + 107 -> 106 ; +106 [label="106: Call _fun_X_nonzero \n n$2=_fun_get_global_ref() [line 125]\n _fun_X_nonzero(n$2:class X ) [line 125]\n REMOVE_TEMPS(n$2); [line 125]\n " shape="box"] + + + 106 -> 105 ; +105 [label="105: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 126]\n n$1=_fun_X_div(n$0:class X ) [line 126]\n REMOVE_TEMPS(n$0,n$1); [line 126]\n APPLY_ABSTRACTION; [line 126]\n " shape="box"] + + + 105 -> 104 ; +104 [label="104: Exit get_global_ref_div1_method \n " color=yellow style=filled] + + +103 [label="103: Start get_global_ref_div1_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 123]\n " color=yellow style=filled] + + + 103 -> 107 ; +102 [label="102: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ref() [line 118]\n *n$3.f:int =1 [line 118]\n REMOVE_TEMPS(n$3); [line 118]\n " shape="box"] + + + 102 -> 101 ; +101 [label="101: Call _fun_X_zero \n n$2=_fun_get_global_ref() [line 119]\n _fun_X_zero(n$2:class X ) [line 119]\n REMOVE_TEMPS(n$2); [line 119]\n " shape="box"] + + + 101 -> 100 ; +100 [label="100: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 120]\n n$1=_fun_X_div(n$0:class X ) [line 120]\n REMOVE_TEMPS(n$0,n$1); [line 120]\n APPLY_ABSTRACTION; [line 120]\n " shape="box"] + + + 100 -> 99 ; +99 [label="99: Exit get_global_ref_div0_method \n " color=yellow style=filled] + + +98 [label="98: Start get_global_ref_div0_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 117]\n " color=yellow style=filled] + + + 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 -> 96 ; +96 [label="96: Return Stmt \n n$0=*&x:class X & [line 114]\n n$1=_fun_X_div(n$0:class X ) [line 114]\n *&return:int =n$1 [line 114]\n REMOVE_TEMPS(n$0,n$1); [line 114]\n NULLIFY(&x,false); [line 114]\n APPLY_ABSTRACTION; [line 114]\n " shape="box"] + + + 96 -> 95 ; +95 [label="95: Exit field_div1_ref \n " color=yellow style=filled] + + +94 [label="94: Start field_div1_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 112]\n " color=yellow style=filled] + + + 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 -> 92 ; +92 [label="92: Return Stmt \n n$0=*&x:class X & [line 109]\n n$1=_fun_X_div(n$0:class X ) [line 109]\n *&return:int =n$1 [line 109]\n REMOVE_TEMPS(n$0,n$1); [line 109]\n NULLIFY(&x,false); [line 109]\n APPLY_ABSTRACTION; [line 109]\n " shape="box"] + + + 92 -> 91 ; +91 [label="91: Exit field_div0_ref \n " color=yellow style=filled] + + +90 [label="90: Start field_div0_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 107]\n " color=yellow style=filled] + + + 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 -> 88 ; +88 [label="88: Return Stmt \n n$0=*&x:class X & [line 104]\n n$1=_fun_X_div(n$0:class X ) [line 104]\n *&return:int =n$1 [line 104]\n REMOVE_TEMPS(n$0,n$1); [line 104]\n NULLIFY(&x,false); [line 104]\n APPLY_ABSTRACTION; [line 104]\n " shape="box"] + + + 88 -> 87 ; +87 [label="87: Exit method_div1_ref \n " color=yellow style=filled] + + +86 [label="86: Start method_div1_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 102]\n " color=yellow style=filled] + + + 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 -> 84 ; +84 [label="84: Return Stmt \n n$0=*&x:class X & [line 99]\n n$1=_fun_X_div(n$0:class X ) [line 99]\n *&return:int =n$1 [line 99]\n REMOVE_TEMPS(n$0,n$1); [line 99]\n NULLIFY(&x,false); [line 99]\n APPLY_ABSTRACTION; [line 99]\n " shape="box"] + + + 84 -> 83 ; +83 [label="83: Exit method_div0_ref \n " color=yellow style=filled] + + +82 [label="82: Start method_div0_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 97]\n " color=yellow style=filled] + + + 82 -> 85 ; +81 [label="81: Call _fun_X_zero \n n$3=_fun_get_global_ptr() [line 92]\n _fun_X_zero(n$3:class X ) [line 92]\n REMOVE_TEMPS(n$3); [line 92]\n " shape="box"] + + + 81 -> 80 ; +80 [label="80: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ptr() [line 93]\n *n$2.f:int =1 [line 93]\n REMOVE_TEMPS(n$2); [line 93]\n " shape="box"] + + + 80 -> 79 ; +79 [label="79: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 94]\n n$1=_fun_X_div(n$0:class X ) [line 94]\n REMOVE_TEMPS(n$0,n$1); [line 94]\n APPLY_ABSTRACTION; [line 94]\n " shape="box"] + + + 79 -> 78 ; +78 [label="78: Exit get_global_ptr_div1_field \n " color=yellow style=filled] + + +77 [label="77: Start get_global_ptr_div1_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 91]\n " color=yellow style=filled] + + + 77 -> 81 ; +76 [label="76: Call _fun_X_nonzero \n n$3=_fun_get_global_ptr() [line 86]\n _fun_X_nonzero(n$3:class X ) [line 86]\n REMOVE_TEMPS(n$3); [line 86]\n " shape="box"] + + + 76 -> 75 ; +75 [label="75: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ptr() [line 87]\n *n$2.f:int =0 [line 87]\n REMOVE_TEMPS(n$2); [line 87]\n " shape="box"] + + + 75 -> 74 ; +74 [label="74: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 88]\n n$1=_fun_X_div(n$0:class X ) [line 88]\n REMOVE_TEMPS(n$0,n$1); [line 88]\n APPLY_ABSTRACTION; [line 88]\n " shape="box"] + + + 74 -> 73 ; +73 [label="73: Exit get_global_ptr_div0_field \n " color=yellow style=filled] + + +72 [label="72: Start get_global_ptr_div0_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 85]\n " color=yellow style=filled] + + + 72 -> 76 ; +71 [label="71: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ptr() [line 80]\n *n$3.f:int =0 [line 80]\n REMOVE_TEMPS(n$3); [line 80]\n " shape="box"] + + + 71 -> 70 ; +70 [label="70: Call _fun_X_nonzero \n n$2=_fun_get_global_ptr() [line 81]\n _fun_X_nonzero(n$2:class X ) [line 81]\n REMOVE_TEMPS(n$2); [line 81]\n " shape="box"] + + + 70 -> 69 ; +69 [label="69: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 82]\n n$1=_fun_X_div(n$0:class X ) [line 82]\n REMOVE_TEMPS(n$0,n$1); [line 82]\n APPLY_ABSTRACTION; [line 82]\n " shape="box"] + + + 69 -> 68 ; +68 [label="68: Exit get_global_ptr_div1_method \n " color=yellow style=filled] + + +67 [label="67: Start get_global_ptr_div1_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 79]\n " color=yellow style=filled] + + + 67 -> 71 ; +66 [label="66: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ptr() [line 74]\n *n$3.f:int =1 [line 74]\n REMOVE_TEMPS(n$3); [line 74]\n " shape="box"] + + + 66 -> 65 ; +65 [label="65: Call _fun_X_zero \n n$2=_fun_get_global_ptr() [line 75]\n _fun_X_zero(n$2:class X ) [line 75]\n REMOVE_TEMPS(n$2); [line 75]\n " shape="box"] + + + 65 -> 64 ; +64 [label="64: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 76]\n n$1=_fun_X_div(n$0:class X ) [line 76]\n REMOVE_TEMPS(n$0,n$1); [line 76]\n APPLY_ABSTRACTION; [line 76]\n " shape="box"] + + + 64 -> 63 ; +63 [label="63: Exit get_global_ptr_div0_method \n " color=yellow style=filled] + + +62 [label="62: Start get_global_ptr_div0_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 73]\n " color=yellow style=filled] + + + 62 -> 66 ; +61 [label="61: Call _fun_set_field_ptr \n n$3=*&x:class X * [line 68]\n _fun_set_field_ptr(n$3:class X *,1:int ) [line 68]\n REMOVE_TEMPS(n$3); [line 68]\n " shape="box"] + + + 61 -> 60 ; +60 [label="60: Return Stmt \n n$1=*&x:class X * [line 69]\n n$2=_fun_X_div(n$1:class X ) [line 69]\n *&return:int =n$2 [line 69]\n REMOVE_TEMPS(n$1,n$2); [line 69]\n NULLIFY(&x,false); [line 69]\n APPLY_ABSTRACTION; [line 69]\n " shape="box"] + + + 60 -> 56 ; +59 [label="59: Prune (false branch) \n n$0=*&x:class X * [line 67]\n PRUNE((n$0 == 0), false); [line 67]\n REMOVE_TEMPS(n$0); [line 67]\n " shape="invhouse"] + + + 59 -> 57 ; +58 [label="58: Prune (true branch) \n n$0=*&x:class X * [line 67]\n PRUNE((n$0 != 0), true); [line 67]\n REMOVE_TEMPS(n$0); [line 67]\n " shape="invhouse"] + + + 58 -> 61 ; +57 [label="57: + \n NULLIFY(&x,false); [line 67]\n " ] + + + 57 -> 56 ; +56 [label="56: Exit field_div1_ptr \n " color=yellow style=filled] + + +55 [label="55: Start field_div1_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 66]\n " color=yellow style=filled] + + + 55 -> 58 ; + 55 -> 59 ; +54 [label="54: Call _fun_set_field_ptr \n n$3=*&x:class X * [line 61]\n _fun_set_field_ptr(n$3:class X *,0:int ) [line 61]\n REMOVE_TEMPS(n$3); [line 61]\n " shape="box"] + + + 54 -> 53 ; +53 [label="53: Return Stmt \n n$1=*&x:class X * [line 62]\n n$2=_fun_X_div(n$1:class X ) [line 62]\n *&return:int =n$2 [line 62]\n REMOVE_TEMPS(n$1,n$2); [line 62]\n NULLIFY(&x,false); [line 62]\n APPLY_ABSTRACTION; [line 62]\n " shape="box"] + + + 53 -> 49 ; +52 [label="52: Prune (false branch) \n n$0=*&x:class X * [line 60]\n PRUNE((n$0 == 0), false); [line 60]\n REMOVE_TEMPS(n$0); [line 60]\n " shape="invhouse"] + + + 52 -> 50 ; +51 [label="51: Prune (true branch) \n n$0=*&x:class X * [line 60]\n PRUNE((n$0 != 0), true); [line 60]\n REMOVE_TEMPS(n$0); [line 60]\n " shape="invhouse"] + + + 51 -> 54 ; +50 [label="50: + \n NULLIFY(&x,false); [line 60]\n " ] + + + 50 -> 49 ; +49 [label="49: Exit field_div0_ptr \n " color=yellow style=filled] + + +48 [label="48: Start field_div0_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 59]\n " color=yellow style=filled] + + + 48 -> 51 ; + 48 -> 52 ; +47 [label="47: Call _fun_nonzero_ptr \n n$3=*&x:class X * [line 54]\n _fun_nonzero_ptr(n$3:class X *) [line 54]\n REMOVE_TEMPS(n$3); [line 54]\n " shape="box"] + + + 47 -> 46 ; +46 [label="46: Return Stmt \n n$1=*&x:class X * [line 55]\n n$2=_fun_X_div(n$1:class X ) [line 55]\n *&return:int =n$2 [line 55]\n REMOVE_TEMPS(n$1,n$2); [line 55]\n NULLIFY(&x,false); [line 55]\n APPLY_ABSTRACTION; [line 55]\n " shape="box"] + + + 46 -> 42 ; +45 [label="45: Prune (false branch) \n n$0=*&x:class X * [line 53]\n PRUNE((n$0 == 0), false); [line 53]\n REMOVE_TEMPS(n$0); [line 53]\n " shape="invhouse"] + + + 45 -> 43 ; +44 [label="44: Prune (true branch) \n n$0=*&x:class X * [line 53]\n PRUNE((n$0 != 0), true); [line 53]\n REMOVE_TEMPS(n$0); [line 53]\n " shape="invhouse"] + + + 44 -> 47 ; +43 [label="43: + \n NULLIFY(&x,false); [line 53]\n " ] + + + 43 -> 42 ; +42 [label="42: Exit method_div1_ptr \n " color=yellow style=filled] + + +41 [label="41: Start method_div1_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 52]\n " color=yellow style=filled] + + + 41 -> 44 ; + 41 -> 45 ; +40 [label="40: Call _fun_zero_ptr \n n$3=*&x:class X * [line 47]\n _fun_zero_ptr(n$3:class X *) [line 47]\n REMOVE_TEMPS(n$3); [line 47]\n " shape="box"] + + + 40 -> 39 ; +39 [label="39: Return Stmt \n n$1=*&x:class X * [line 48]\n n$2=_fun_X_div(n$1:class X ) [line 48]\n *&return:int =n$2 [line 48]\n REMOVE_TEMPS(n$1,n$2); [line 48]\n NULLIFY(&x,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"] + + + 39 -> 35 ; +38 [label="38: Prune (false branch) \n n$0=*&x:class X * [line 46]\n PRUNE((n$0 == 0), false); [line 46]\n REMOVE_TEMPS(n$0); [line 46]\n " shape="invhouse"] + + + 38 -> 36 ; +37 [label="37: Prune (true branch) \n n$0=*&x:class X * [line 46]\n PRUNE((n$0 != 0), true); [line 46]\n REMOVE_TEMPS(n$0); [line 46]\n " shape="invhouse"] + + + 37 -> 40 ; +36 [label="36: + \n NULLIFY(&x,false); [line 46]\n " ] + + + 36 -> 35 ; +35 [label="35: Exit method_div0_ptr \n " color=yellow style=filled] + + +34 [label="34: Start method_div0_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 45]\n " color=yellow style=filled] + + + 34 -> 37 ; + 34 -> 38 ; +33 [label="33: Return Stmt \n *&return:class X &=&#GB$global [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"] + + + 33 -> 32 ; +32 [label="32: Exit get_global_ref \n " color=yellow style=filled] + + +31 [label="31: Start get_global_ref\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 43]\n " color=yellow style=filled] + + + 31 -> 33 ; +30 [label="30: Return Stmt \n *&return:class X *=&#GB$global [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"] + + + 30 -> 29 ; +29 [label="29: Exit get_global_ptr \n " color=yellow style=filled] + + +28 [label="28: Start get_global_ptr\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 42]\n " color=yellow style=filled] + + + 28 -> 30 ; +27 [label="27: BinaryOperatorStmt: Assign \n n$0=*&x:class X & [line 38]\n n$1=*&val:int [line 38]\n *n$0.f:int =n$1 [line 38]\n REMOVE_TEMPS(n$0,n$1); [line 38]\n NULLIFY(&val,false); [line 38]\n NULLIFY(&x,false); [line 38]\n APPLY_ABSTRACTION; [line 38]\n " shape="box"] + + + 27 -> 26 ; +26 [label="26: Exit set_field_ref \n " color=yellow style=filled] + + +25 [label="25: Start set_field_ref\nFormals: x:class X & val:int \nLocals: \n DECLARE_LOCALS(&return); [line 37]\n " color=yellow style=filled] + + + 25 -> 27 ; +24 [label="24: Call _fun_X_nonzero \n n$0=*&x:class X & [line 34]\n _fun_X_nonzero(n$0:class X ) [line 34]\n REMOVE_TEMPS(n$0); [line 34]\n NULLIFY(&x,false); [line 34]\n APPLY_ABSTRACTION; [line 34]\n " shape="box"] + + + 24 -> 23 ; +23 [label="23: Exit nonzero_ref \n " color=yellow style=filled] + + +22 [label="22: Start nonzero_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 33]\n " color=yellow style=filled] + + + 22 -> 24 ; +21 [label="21: Call _fun_X_zero \n n$0=*&x:class X & [line 30]\n _fun_X_zero(n$0:class X ) [line 30]\n REMOVE_TEMPS(n$0); [line 30]\n NULLIFY(&x,false); [line 30]\n APPLY_ABSTRACTION; [line 30]\n " shape="box"] + + + 21 -> 20 ; +20 [label="20: Exit zero_ref \n " color=yellow style=filled] + + +19 [label="19: Start zero_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 29]\n " color=yellow style=filled] + + + 19 -> 21 ; +18 [label="18: BinaryOperatorStmt: Assign \n n$0=*&x:class X * [line 26]\n n$1=*&val:int [line 26]\n *n$0.f:int =n$1 [line 26]\n REMOVE_TEMPS(n$0,n$1); [line 26]\n NULLIFY(&val,false); [line 26]\n NULLIFY(&x,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"] + + + 18 -> 17 ; +17 [label="17: Exit set_field_ptr \n " color=yellow style=filled] + + +16 [label="16: Start set_field_ptr\nFormals: x:class X * val:int \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n " color=yellow style=filled] + + + 16 -> 18 ; +15 [label="15: Call _fun_X_nonzero \n n$0=*&x:class X * [line 22]\n _fun_X_nonzero(n$0:class X ) [line 22]\n REMOVE_TEMPS(n$0); [line 22]\n NULLIFY(&x,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"] + + + 15 -> 14 ; +14 [label="14: Exit nonzero_ptr \n " color=yellow style=filled] + + +13 [label="13: Start nonzero_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 21]\n " color=yellow style=filled] + + + 13 -> 15 ; +12 [label="12: Call _fun_X_zero \n n$0=*&x:class X * [line 18]\n _fun_X_zero(n$0:class X ) [line 18]\n REMOVE_TEMPS(n$0); [line 18]\n NULLIFY(&x,false); [line 18]\n APPLY_ABSTRACTION; [line 18]\n " shape="box"] + + + 12 -> 11 ; +11 [label="11: Exit zero_ptr \n " color=yellow style=filled] + + +10 [label="10: Start zero_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 17]\n " color=yellow style=filled] + + + 10 -> 12 ; +9 [label="9: Return Stmt \n n$0=*&this:class X * [line 14]\n n$1=*n$0.f:int [line 14]\n *&return:int =(1 / n$1) [line 14]\n REMOVE_TEMPS(n$0,n$1); [line 14]\n NULLIFY(&this,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"] + + + 9 -> 8 ; +8 [label="8: Exit X_div \n " color=yellow style=filled] + + +7 [label="7: Start X_div\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled] + + + 7 -> 9 ; +6 [label="6: BinaryOperatorStmt: Assign \n n$0=*&this:class X * [line 13]\n *n$0.f:int =0 [line 13]\n REMOVE_TEMPS(n$0); [line 13]\n NULLIFY(&this,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit X_zero \n " color=yellow style=filled] + + +4 [label="4: Start X_zero\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled] + + + 4 -> 6 ; +3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&this:class X * [line 12]\n *n$0.f:int =1 [line 12]\n REMOVE_TEMPS(n$0); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit X_nonzero \n " color=yellow style=filled] + + +1 [label="1: Start X_nonzero\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp new file mode 100644 index 000000000..746b280f1 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2015 - 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. +*/ + +void zero_ptr(int* p) { *p = 0; } +void zero_ref(int& p) { p = 0; } + +int ptr_div0() { + int a = 2; + int* p = &a; + *p = 0; + return 1/a; +} + +int ptr_div0_function() { + int a = 2; + zero_ptr(&a); + return 1/a; +} + +int ptr_div0_function_temp_var() { + int a = 2; + int *r = &a; + zero_ptr(r); + return 1/a; +} + +int ref_div0() { + int a = 2; + int& r = a; + r = 0; + return 1/a; +} + +int ref_div0_function() { + int a = 2; + zero_ref(a); + return 1/a; +} + +int ref_div0_function_temp_var() { + int a = 2; + int &r = a; + zero_ref(r); + return 1/a; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp.dot new file mode 100644 index 000000000..9cb8c64f6 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp.dot @@ -0,0 +1,154 @@ +digraph iCFG { +40 [label="40: DeclStmt \n *&a:int =2 [line 47]\n " shape="box"] + + + 40 -> 39 ; +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 -> 37 ; +37 [label="37: Return Stmt \n n$0=*&a:int [line 50]\n *&return:int =(1 / n$0) [line 50]\n REMOVE_TEMPS(n$0); [line 50]\n NULLIFY(&a,false); [line 50]\n APPLY_ABSTRACTION; [line 50]\n " shape="box"] + + + 37 -> 36 ; +36 [label="36: Exit ref_div0_function_temp_var \n " color=yellow style=filled] + + +35 [label="35: Start ref_div0_function_temp_var\nFormals: \nLocals: r:int & a:int \n DECLARE_LOCALS(&return,&r,&a); [line 46]\n NULLIFY(&r,false); [line 46]\n " color=yellow style=filled] + + + 35 -> 40 ; +34 [label="34: DeclStmt \n *&a:int =2 [line 41]\n " shape="box"] + + + 34 -> 33 ; +33 [label="33: Call _fun_zero_ref \n _fun_zero_ref(&a:int ) [line 42]\n " shape="box"] + + + 33 -> 32 ; +32 [label="32: Return Stmt \n n$0=*&a:int [line 43]\n *&return:int =(1 / n$0) [line 43]\n REMOVE_TEMPS(n$0); [line 43]\n NULLIFY(&a,false); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"] + + + 32 -> 31 ; +31 [label="31: Exit ref_div0_function \n " color=yellow style=filled] + + +30 [label="30: Start ref_div0_function\nFormals: \nLocals: a:int \n DECLARE_LOCALS(&return,&a); [line 40]\n " color=yellow style=filled] + + + 30 -> 34 ; +29 [label="29: DeclStmt \n *&a:int =2 [line 34]\n " shape="box"] + + + 29 -> 28 ; +28 [label="28: DeclStmt \n *&r:int =&a [line 35]\n " shape="box"] + + + 28 -> 27 ; +27 [label="27: BinaryOperatorStmt: Assign \n n$1=*&r:int & [line 36]\n *n$1:int =0 [line 36]\n REMOVE_TEMPS(n$1); [line 36]\n NULLIFY(&r,false); [line 36]\n " shape="box"] + + + 27 -> 26 ; +26 [label="26: Return Stmt \n n$0=*&a:int [line 37]\n *&return:int =(1 / n$0) [line 37]\n REMOVE_TEMPS(n$0); [line 37]\n NULLIFY(&a,false); [line 37]\n APPLY_ABSTRACTION; [line 37]\n " shape="box"] + + + 26 -> 25 ; +25 [label="25: Exit ref_div0 \n " color=yellow style=filled] + + +24 [label="24: Start ref_div0\nFormals: \nLocals: r:int & a:int \n DECLARE_LOCALS(&return,&r,&a); [line 33]\n NULLIFY(&r,false); [line 33]\n " color=yellow style=filled] + + + 24 -> 29 ; +23 [label="23: DeclStmt \n *&a:int =2 [line 27]\n " shape="box"] + + + 23 -> 22 ; +22 [label="22: DeclStmt \n *&r:int *=&a [line 28]\n " shape="box"] + + + 22 -> 21 ; +21 [label="21: Call _fun_zero_ptr \n n$1=*&r:int * [line 29]\n _fun_zero_ptr(n$1:int *) [line 29]\n REMOVE_TEMPS(n$1); [line 29]\n NULLIFY(&r,false); [line 29]\n " shape="box"] + + + 21 -> 20 ; +20 [label="20: Return Stmt \n n$0=*&a:int [line 30]\n *&return:int =(1 / n$0) [line 30]\n REMOVE_TEMPS(n$0); [line 30]\n NULLIFY(&a,false); [line 30]\n APPLY_ABSTRACTION; [line 30]\n " shape="box"] + + + 20 -> 19 ; +19 [label="19: Exit ptr_div0_function_temp_var \n " color=yellow style=filled] + + +18 [label="18: Start ptr_div0_function_temp_var\nFormals: \nLocals: r:int * a:int \n DECLARE_LOCALS(&return,&r,&a); [line 26]\n NULLIFY(&r,false); [line 26]\n " color=yellow style=filled] + + + 18 -> 23 ; +17 [label="17: DeclStmt \n *&a:int =2 [line 21]\n " shape="box"] + + + 17 -> 16 ; +16 [label="16: Call _fun_zero_ptr \n _fun_zero_ptr(&a:int *) [line 22]\n " shape="box"] + + + 16 -> 15 ; +15 [label="15: Return Stmt \n n$0=*&a:int [line 23]\n *&return:int =(1 / n$0) [line 23]\n REMOVE_TEMPS(n$0); [line 23]\n NULLIFY(&a,false); [line 23]\n APPLY_ABSTRACTION; [line 23]\n " shape="box"] + + + 15 -> 14 ; +14 [label="14: Exit ptr_div0_function \n " color=yellow style=filled] + + +13 [label="13: Start ptr_div0_function\nFormals: \nLocals: a:int \n DECLARE_LOCALS(&return,&a); [line 20]\n " color=yellow style=filled] + + + 13 -> 17 ; +12 [label="12: DeclStmt \n *&a:int =2 [line 14]\n " shape="box"] + + + 12 -> 11 ; +11 [label="11: DeclStmt \n *&p:int *=&a [line 15]\n " shape="box"] + + + 11 -> 10 ; +10 [label="10: BinaryOperatorStmt: Assign \n n$1=*&p:int * [line 16]\n *n$1:int =0 [line 16]\n REMOVE_TEMPS(n$1); [line 16]\n NULLIFY(&p,false); [line 16]\n " shape="box"] + + + 10 -> 9 ; +9 [label="9: Return Stmt \n n$0=*&a:int [line 17]\n *&return:int =(1 / n$0) [line 17]\n REMOVE_TEMPS(n$0); [line 17]\n NULLIFY(&a,false); [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"] + + + 9 -> 8 ; +8 [label="8: Exit ptr_div0 \n " color=yellow style=filled] + + +7 [label="7: Start ptr_div0\nFormals: \nLocals: p:int * a:int \n DECLARE_LOCALS(&return,&p,&a); [line 13]\n NULLIFY(&p,false); [line 13]\n " color=yellow style=filled] + + + 7 -> 12 ; +6 [label="6: BinaryOperatorStmt: Assign \n n$0=*&p:int & [line 11]\n *n$0:int =0 [line 11]\n REMOVE_TEMPS(n$0); [line 11]\n NULLIFY(&p,false); [line 11]\n APPLY_ABSTRACTION; [line 11]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit zero_ref \n " color=yellow style=filled] + + +4 [label="4: Start zero_ref\nFormals: p:int &\nLocals: \n DECLARE_LOCALS(&return); [line 11]\n " color=yellow style=filled] + + + 4 -> 6 ; +3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&p:int * [line 10]\n *n$0:int =0 [line 10]\n REMOVE_TEMPS(n$0); [line 10]\n NULLIFY(&p,false); [line 10]\n APPLY_ABSTRACTION; [line 10]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit zero_ptr \n " color=yellow style=filled] + + +1 [label="1: Start zero_ptr\nFormals: p:int *\nLocals: \n DECLARE_LOCALS(&return); [line 10]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/unbox.cpp b/infer/tests/codetoanalyze/cpp/frontend/reference/unbox.cpp new file mode 100644 index 000000000..e9f8ebcc3 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/unbox.cpp @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2015 - 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 fun_p(int *p) { return *p;} +int fun_v(int p) { return p;} +int fun_r(int &p) { return p;} + +// cfgs should look similar for unbox_ref and unbox_ptr + +// test conversions from int& to {int*, int, int&) +void unbox_ref() { + int a = 3; + int& r = a; + + fun_p(&r); + fun_v(r); + fun_r(r); +} + +// test conversions from int* to {int*, int, int&) +void unbox_ptr() { + int a = 3; + int *p = &a; + + fun_p(p); + fun_v(*p); + fun_r(*p); +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/reference/unbox.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/reference/unbox.cpp.dot new file mode 100644 index 000000000..0b58dafa6 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/reference/unbox.cpp.dot @@ -0,0 +1,89 @@ +digraph iCFG { +23 [label="23: DeclStmt \n *&a:int =3 [line 28]\n " shape="box"] + + + 23 -> 22 ; +22 [label="22: DeclStmt \n *&p:int *=&a [line 29]\n " shape="box"] + + + 22 -> 21 ; +21 [label="21: Call _fun_fun_p \n n$5=*&p:int * [line 31]\n n$6=_fun_fun_p(n$5:int *) [line 31]\n REMOVE_TEMPS(n$5,n$6); [line 31]\n " shape="box"] + + + 21 -> 20 ; +20 [label="20: Call _fun_fun_v \n n$2=*&p:int * [line 32]\n n$3=*n$2:int [line 32]\n n$4=_fun_fun_v(n$3:int ) [line 32]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 32]\n " shape="box"] + + + 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 -> 18 ; +18 [label="18: Exit unbox_ptr \n " color=yellow style=filled] + + +17 [label="17: Start unbox_ptr\nFormals: \nLocals: p:int * a:int \n DECLARE_LOCALS(&return,&p,&a); [line 27]\n NULLIFY(&p,false); [line 27]\n " color=yellow style=filled] + + + 17 -> 23 ; +16 [label="16: DeclStmt \n *&a:int =3 [line 18]\n " shape="box"] + + + 16 -> 15 ; +15 [label="15: DeclStmt \n *&r:int =&a [line 19]\n " shape="box"] + + + 15 -> 14 ; +14 [label="14: Call _fun_fun_p \n n$5=*&r:int & [line 21]\n n$6=_fun_fun_p(n$5:int *) [line 21]\n REMOVE_TEMPS(n$5,n$6); [line 21]\n " shape="box"] + + + 14 -> 13 ; +13 [label="13: Call _fun_fun_v \n n$2=*&r:int & [line 22]\n n$3=*n$2:int [line 22]\n n$4=_fun_fun_v(n$3:int ) [line 22]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 22]\n " shape="box"] + + + 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 -> 11 ; +11 [label="11: Exit unbox_ref \n " color=yellow style=filled] + + +10 [label="10: Start unbox_ref\nFormals: \nLocals: r:int & a:int \n DECLARE_LOCALS(&return,&r,&a); [line 17]\n NULLIFY(&r,false); [line 17]\n " color=yellow style=filled] + + + 10 -> 16 ; +9 [label="9: Return Stmt \n n$0=*&p:int & [line 12]\n n$1=*n$0:int [line 12]\n *&return:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&p,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"] + + + 9 -> 8 ; +8 [label="8: Exit fun_r \n " color=yellow style=filled] + + +7 [label="7: Start fun_r\nFormals: p:int &\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled] + + + 7 -> 9 ; +6 [label="6: Return Stmt \n n$0=*&p:int [line 11]\n *&return:int =n$0 [line 11]\n REMOVE_TEMPS(n$0); [line 11]\n NULLIFY(&p,false); [line 11]\n APPLY_ABSTRACTION; [line 11]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit fun_v \n " color=yellow style=filled] + + +4 [label="4: Start fun_v\nFormals: p:int \nLocals: \n DECLARE_LOCALS(&return); [line 11]\n " color=yellow style=filled] + + + 4 -> 6 ; +3 [label="3: Return Stmt \n n$0=*&p:int * [line 10]\n n$1=*n$0:int [line 10]\n *&return:int =n$1 [line 10]\n REMOVE_TEMPS(n$0,n$1); [line 10]\n NULLIFY(&p,false); [line 10]\n APPLY_ABSTRACTION; [line 10]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit fun_p \n " color=yellow style=filled] + + +1 [label="1: Start fun_p\nFormals: p:int *\nLocals: \n DECLARE_LOCALS(&return); [line 10]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/endtoend/cpp/ReferenceStructTest.java b/infer/tests/endtoend/cpp/ReferenceStructTest.java new file mode 100644 index 000000000..c24845860 --- /dev/null +++ b/infer/tests/endtoend/cpp/ReferenceStructTest.java @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2015 - 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 ReferenceStructTest { + + public static final String FILE = + "infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp"; + + private static ImmutableList 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 = { + "method_div0_ptr", + "field_div0_ptr", + "get_global_ptr_div0_method", + "get_global_ptr_div0_field", + "method_div0_ref", + "field_div0_ref", + "get_global_ref_div0_method", + "get_global_ref_div0_field" + }; + assertThat( + "Results should contain the expected divide by zero", + inferResults, + containsExactly( + DIVIDE_BY_ZERO, + FILE, + procedures + ) + ); + } +} diff --git a/infer/tests/endtoend/cpp/ReferenceTypeTest.java b/infer/tests/endtoend/cpp/ReferenceTypeTest.java new file mode 100644 index 000000000..de53fb318 --- /dev/null +++ b/infer/tests/endtoend/cpp/ReferenceTypeTest.java @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2015 - 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 ReferenceTypeTest { + + public static final String FILE = + "infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp"; + + private static ImmutableList 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 = { + "ptr_div0", + "ptr_div0_function", + "ptr_div0_function_temp_var", + "ref_div0", + "ref_div0_function", + "ref_div0_function_temp_var" + }; + assertThat( + "Results should contain the expected divide by zero", + inferResults, + containsExactly( + DIVIDE_BY_ZERO, + FILE, + procedures + ) + ); + } +} diff --git a/infer/tests/frontend/cpp/ReferenceTest.java b/infer/tests/frontend/cpp/ReferenceTest.java new file mode 100644 index 000000000..c0fdb11ed --- /dev/null +++ b/infer/tests/frontend/cpp/ReferenceTest.java @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2015 - 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 frontend.cpp; + +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.ClangFrontendUtils; + +public class ReferenceTest { + + String basePath = "infer/tests/codetoanalyze/cpp/frontend/reference/"; + + @Rule + public DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder(); + + void frontendTest(String fileRelative) throws InterruptedException, IOException, InferException { + ClangFrontendUtils.createAndCompareCppDotFiles(folder, basePath + fileRelative); + } + + @Test + public void testBoxDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("box.cpp"); + } + + @Test + public void testUnboxDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("unbox.cpp"); + } + + @Test + public void testInitDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("init.cpp"); + } + + @Test + public void testMemberAccessDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("member_access.cpp"); + } + + @Test + public void testMemberAccessFromReturnDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("member_access_from_return.cpp"); + } + + @Test + public void testReferenceTypeE2EDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("reference_type_e2e.cpp"); + } + + @Test + public void testReferenceStructE2EDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("reference_struct_e2e.cpp"); + } +}