diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 58d97cb7f..f0647dbb0 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -1751,7 +1751,7 @@ struct leaf_nodes = res_trans_stmt.leaf_nodes; ids = res_trans_stmt.ids @ cast_ids; instrs = res_trans_stmt.instrs @ cast_inst; - exps = [(cast_exp, typ)] } + exps = [cast_exp] } (* function used in the computation for both Member_Expr and ObjCIVarRefExpr *) and do_memb_ivar_ref_exp trans_state expr_info stmt_info stmt_list decl_ref = diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index d69465c5e..4f7503a39 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -385,27 +385,33 @@ let dereference_value_from_result sil_loc trans_result ~strip_pointer = let cast_operation context cast_kind exps cast_typ sil_loc is_objc_bridged = let (exp, typ) = extract_exp_from_list exps "" in + let exp_typ = match cast_kind with + | `UncheckedDerivedToBase -> typ (* This cast ignores change of type *) + | _ -> cast_typ (* by default use the return type of cast expr *) in if is_objc_bridged then let id, instr, exp = create_cast_instrs context exp typ cast_typ sil_loc in - [id], [instr], exp + [id], [instr], (exp, exp_typ) else match cast_kind with | `NoOp | `BitCast | `IntegralCast + | `DerivedToBase + | `UncheckedDerivedToBase | `IntegralToBoolean -> (* This is treated as a nop by returning the same expressions exps*) - ([],[], exp) + ([], [], (exp, exp_typ)) | `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.*) - dereference_var_sil (exp, typ) sil_loc + let ids, instrs, deref_exp = dereference_var_sil (exp, typ) sil_loc in + ids, instrs, (deref_exp, exp_typ) | `CPointerToObjCPointerCast -> - ([], [], Sil.Cast(typ, exp)) + [], [], (Sil.Cast(typ, exp), exp_typ) | _ -> Printing.log_err "\nWARNING: Missing translation for Cast Kind %s. The construct has been ignored...\n" (Clang_ast_j.string_of_cast_kind cast_kind); - ([],[], exp) + ([],[], (exp, exp_typ)) let trans_assertion_failure sil_loc context = let assert_fail_builtin = Sil.Const (Sil.Cfun SymExec.ModelBuiltins.__infer_fail) in diff --git a/infer/src/clang/cTrans_utils.mli b/infer/src/clang/cTrans_utils.mli index 2019ca3a4..39ade7d72 100644 --- a/infer/src/clang/cTrans_utils.mli +++ b/infer/src/clang/cTrans_utils.mli @@ -81,7 +81,7 @@ val dereference_value_from_result : Location.t -> trans_result -> strip_pointer: 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 + bool -> Ident.t list * Sil.instr list * (Sil.exp * Sil.typ) val trans_assertion_failure : Location.t -> CContext.t -> trans_result diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.cpp.dot index 68df41736..1ebc9aa7f 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.cpp.dot @@ -19,7 +19,7 @@ digraph iCFG { 20 -> 19 ; -19 [label="19: Call _fun_Base_fun \n n$6=*&s2:class Sub * [line 28]\n n$7=_fun_Base_fun(n$6:class Base *) [line 28]\n REMOVE_TEMPS(n$6,n$7); [line 28]\n " shape="box"] +19 [label="19: Call _fun_Base_fun \n n$6=*&s2:class Sub * [line 28]\n n$7=_fun_Base_fun(n$6:class Sub *) [line 28]\n REMOVE_TEMPS(n$6,n$7); [line 28]\n " shape="box"] 19 -> 18 ; diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp index 27c3d6c69..a55300cb4 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp +++ b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp @@ -46,6 +46,17 @@ int div0_cast_ref(Sub s) { return 1 / b.b1; } +int div0_b1_s(Sub *s) { + s->b1 = 1; + s->s = 1; + return 1 / (s->b1 - s->s); +} + +int div0_s_b1(Sub *s) { + s->b1 = 1; + s->s = 1; + return 1 / (s->b1 - s->s); +} int div1_b1(Sub s) { s.b1 = 1; @@ -57,4 +68,3 @@ int div1_cast(Sub *s) { Base1 *b = s; return 1 / b->b1; } - diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp.dot index 663489be2..f50b6d232 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance_field.cpp.dot @@ -1,38 +1,76 @@ digraph iCFG { -31 [label="31: BinaryOperatorStmt: Assign \n n$3=*&s:class Sub * [line 56]\n *n$3.b1:int =1 [line 56]\n REMOVE_TEMPS(n$3); [line 56]\n " shape="box"] +41 [label="41: BinaryOperatorStmt: Assign \n n$3=*&s:class Sub * [line 67]\n *n$3.b1:int =1 [line 67]\n REMOVE_TEMPS(n$3); [line 67]\n " shape="box"] + + + 41 -> 40 ; +40 [label="40: DeclStmt \n n$2=*&s:class Sub * [line 68]\n *&b:struct Base1 *=n$2 [line 68]\n REMOVE_TEMPS(n$2); [line 68]\n NULLIFY(&s,false); [line 68]\n " shape="box"] + + + 40 -> 39 ; +39 [label="39: Return Stmt \n n$0=*&b:struct Base1 * [line 69]\n n$1=*n$0.b1:int [line 69]\n *&return:int =(1 / n$1) [line 69]\n REMOVE_TEMPS(n$0,n$1); [line 69]\n NULLIFY(&b,false); [line 69]\n APPLY_ABSTRACTION; [line 69]\n " shape="box"] + + + 39 -> 38 ; +38 [label="38: Exit div1_cast \n " color=yellow style=filled] + + +37 [label="37: Start div1_cast\nFormals: s:class Sub *\nLocals: b:struct Base1 * \n DECLARE_LOCALS(&return,&b); [line 66]\n NULLIFY(&b,false); [line 66]\n " color=yellow style=filled] + + + 37 -> 41 ; +36 [label="36: BinaryOperatorStmt: Assign \n *&s.b1:int =1 [line 62]\n " shape="box"] + + + 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,false); [line 63]\n APPLY_ABSTRACTION; [line 63]\n " shape="box"] + + + 35 -> 34 ; +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 -> 36 ; +32 [label="32: BinaryOperatorStmt: Assign \n n$5=*&s:class Sub * [line 56]\n *n$5.b1:int =1 [line 56]\n REMOVE_TEMPS(n$5); [line 56]\n " shape="box"] + + + 32 -> 31 ; +31 [label="31: BinaryOperatorStmt: Assign \n n$4=*&s:class Sub * [line 57]\n *n$4.s:int =1 [line 57]\n REMOVE_TEMPS(n$4); [line 57]\n " shape="box"] 31 -> 30 ; -30 [label="30: DeclStmt \n n$2=*&s:class Sub * [line 57]\n *&b:struct Base1 *=n$2 [line 57]\n REMOVE_TEMPS(n$2); [line 57]\n NULLIFY(&s,false); [line 57]\n " shape="box"] +30 [label="30: Return Stmt \n n$0=*&s:class Sub * [line 58]\n n$1=*n$0.b1:int [line 58]\n n$2=*&s:class Sub * [line 58]\n n$3=*n$2.s:int [line 58]\n *&return:int =(1 / (n$1 - n$3)) [line 58]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 58]\n NULLIFY(&s,false); [line 58]\n APPLY_ABSTRACTION; [line 58]\n " shape="box"] 30 -> 29 ; -29 [label="29: Return Stmt \n n$0=*&b:struct Base1 * [line 58]\n n$1=*n$0.b1:int [line 58]\n *&return:int =(1 / n$1) [line 58]\n REMOVE_TEMPS(n$0,n$1); [line 58]\n NULLIFY(&b,false); [line 58]\n APPLY_ABSTRACTION; [line 58]\n " shape="box"] +29 [label="29: Exit div0_s_b1 \n " color=yellow style=filled] - 29 -> 28 ; -28 [label="28: Exit div1_cast \n " color=yellow style=filled] +28 [label="28: Start div0_s_b1\nFormals: s:class Sub *\nLocals: \n DECLARE_LOCALS(&return); [line 55]\n " color=yellow style=filled] -27 [label="27: Start div1_cast\nFormals: s:class Sub *\nLocals: b:struct Base1 * \n DECLARE_LOCALS(&return,&b); [line 55]\n NULLIFY(&b,false); [line 55]\n " color=yellow style=filled] + 28 -> 32 ; +27 [label="27: BinaryOperatorStmt: Assign \n n$5=*&s:class Sub * [line 50]\n *n$5.b1:int =1 [line 50]\n REMOVE_TEMPS(n$5); [line 50]\n " shape="box"] - 27 -> 31 ; -26 [label="26: BinaryOperatorStmt: Assign \n *&s.b1:int =1 [line 51]\n " shape="box"] + 27 -> 26 ; +26 [label="26: BinaryOperatorStmt: Assign \n n$4=*&s:class Sub * [line 51]\n *n$4.s:int =1 [line 51]\n REMOVE_TEMPS(n$4); [line 51]\n " shape="box"] 26 -> 25 ; -25 [label="25: Return Stmt \n n$0=*&s.b1:int [line 52]\n *&return:int =(1 / n$0) [line 52]\n REMOVE_TEMPS(n$0); [line 52]\n NULLIFY(&s,false); [line 52]\n APPLY_ABSTRACTION; [line 52]\n " shape="box"] +25 [label="25: Return Stmt \n n$0=*&s:class Sub * [line 52]\n n$1=*n$0.b1:int [line 52]\n n$2=*&s:class Sub * [line 52]\n n$3=*n$2.s:int [line 52]\n *&return:int =(1 / (n$1 - n$3)) [line 52]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 52]\n NULLIFY(&s,false); [line 52]\n APPLY_ABSTRACTION; [line 52]\n " shape="box"] 25 -> 24 ; -24 [label="24: Exit div1_b1 \n " color=yellow style=filled] +24 [label="24: Exit div0_b1_s \n " color=yellow style=filled] -23 [label="23: Start div1_b1\nFormals: s:class Sub \nLocals: \n DECLARE_LOCALS(&return); [line 50]\n " color=yellow style=filled] +23 [label="23: Start div0_b1_s\nFormals: s:class Sub *\nLocals: \n DECLARE_LOCALS(&return); [line 49]\n " color=yellow style=filled] - 23 -> 26 ; + 23 -> 27 ; 22 [label="22: BinaryOperatorStmt: Assign \n *&s.b1:int =0 [line 44]\n " shape="box"] diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/operator_overload.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/types/operator_overload.cpp.dot index c1dbca509..0d0553938 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/operator_overload.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/types/operator_overload.cpp.dot @@ -10,7 +10,7 @@ digraph iCFG { 25 -> 27 ; -24 [label="24: Return Stmt \n n$0=*&y:class Y & [line 48]\n n$1=_fun_X_operator[](n$0:class X &,0:int ) [line 48]\n *&return:int =(1 / n$1) [line 48]\n REMOVE_TEMPS(n$0,n$1); [line 48]\n NULLIFY(&y,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"] +24 [label="24: Return Stmt \n n$0=*&y:class Y & [line 48]\n n$1=_fun_X_operator[](n$0:class Y &,0:int ) [line 48]\n *&return:int =(1 / n$1) [line 48]\n REMOVE_TEMPS(n$0,n$1); [line 48]\n NULLIFY(&y,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"] 24 -> 23 ; diff --git a/infer/tests/endtoend/cpp/InheritanceFieldTest.java b/infer/tests/endtoend/cpp/InheritanceFieldTest.java index e13180732..af46f0215 100644 --- a/infer/tests/endtoend/cpp/InheritanceFieldTest.java +++ b/infer/tests/endtoend/cpp/InheritanceFieldTest.java @@ -53,6 +53,8 @@ public class InheritanceFieldTest { "div0_s", "div0_cast", "div0_cast_ref", + "div0_b1_s", + "div0_s_b1", }; assertThat( "Results should contain the expected divide by zero",