From a62ccc7a055f2ead91dcb23079a1f0189c4acf9f Mon Sep 17 00:00:00 2001 From: Dulma Rodriguez Date: Tue, 15 Mar 2016 05:47:27 -0700 Subject: [PATCH] Fixing init list expr when there is no variable or compound literal expression Reviewed By: ddino Differential Revision: D3048294 fb-gh-sync-id: b4b8cd2 shipit-source-id: b4b8cd2 --- infer/src/clang/cTrans.ml | 23 +++++++++++------- infer/src/clang/cTrans_utils.ml | 2 +- infer/src/clang/cTrans_utils.mli | 2 +- .../constructor_struct_init_list.cpp | 17 +++++++++++++ .../constructor_struct_init_list.cpp.dot | 24 +++++++++++++++++++ .../tests/frontend/cpp/ConstructorsTest.java | 6 +++++ 6 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp create mode 100644 infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp.dot diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 654c33608..b3f678982 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -253,6 +253,14 @@ struct let typ = CTypes_decl.type_ptr_to_sil_type tenv type_ptr in (mk_temp_sil_var procdesc var_name_prefix, typ) + let create_var_exp_tmp_var trans_state expr_info var_name = + let context = trans_state.context in + let procdesc = context.CContext.procdesc in + let (pvar, typ) = mk_temp_sil_var_for_expr context.CContext.tenv procdesc + var_name expr_info in + Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, typ)]; + Sil.Lvar pvar, typ + let create_call_instr trans_state return_type function_sil params_sil sil_loc call_flags ~is_objc_method = let ret_id = if (Sil.typ_equal return_type Sil.Tvoid) then [] @@ -374,7 +382,7 @@ struct | _ -> empty_res_trans let implicitValueInitExpr_trans trans_state expr_info = - let (var_exp, _) = extract_var_exp_of_fail trans_state in + let (var_exp, _) = extract_var_exp_or_fail trans_state in let tenv = trans_state.context.CContext.tenv in let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in let exps = var_or_zero_in_init_list tenv var_exp typ ~return_zero:true in @@ -1513,9 +1521,13 @@ struct and initListExpr_trans trans_state stmt_info expr_info stmts = let context = trans_state.context in let tenv = context.tenv in + let (var_exp, typ) = + match trans_state.var_exp_typ with + | Some var_exp_typ -> var_exp_typ + | None -> create_var_exp_tmp_var trans_state expr_info "SIL_init_list__" in + let trans_state = { trans_state with var_exp_typ = Some (var_exp, typ) } in let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in let sil_loc = CLocation.get_sil_location stmt_info context in - let var_exp, _ = extract_var_exp_of_fail trans_state in let var_type = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv expr_info.Clang_ast_t.ei_type_ptr in let lh = var_or_zero_in_init_list tenv var_exp var_type ~return_zero:false in @@ -1955,12 +1967,7 @@ struct let var_exp_typ = if Option.is_some trans_state.var_exp_typ then trans_state.var_exp_typ else - let context = trans_state.context in - let procdesc = context.CContext.procdesc in - let (pvar, typ) = mk_temp_sil_var_for_expr context.CContext.tenv procdesc - "SIL_compound_literal__" expr_info in - Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, typ)]; - Some (Sil.Lvar pvar, typ) in + Some (create_var_exp_tmp_var trans_state expr_info "SIL_compound_literal__") in let trans_state' = { trans_state with var_exp_typ = var_exp_typ } in instruction trans_state' stmt diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index ada6dbcf9..9e17e599f 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -184,7 +184,7 @@ let collect_res_trans l = is_cpp_call_virtual = false; } in collect l empty_res_trans -let extract_var_exp_of_fail transt_state = +let extract_var_exp_or_fail transt_state = match transt_state.var_exp_typ with | Some var_exp_typ -> var_exp_typ | None -> assert false diff --git a/infer/src/clang/cTrans_utils.mli b/infer/src/clang/cTrans_utils.mli index 8fbbdc92a..006d12800 100644 --- a/infer/src/clang/cTrans_utils.mli +++ b/infer/src/clang/cTrans_utils.mli @@ -41,7 +41,7 @@ val empty_res_trans: trans_result val collect_res_trans : trans_result list -> trans_result -val extract_var_exp_of_fail : trans_state -> Sil.exp * Sil.typ +val extract_var_exp_or_fail : trans_state -> Sil.exp * Sil.typ val is_return_temp: continuation option -> bool diff --git a/infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp b/infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp new file mode 100644 index 000000000..3d5569157 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp @@ -0,0 +1,17 @@ +/* + * 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. + */ + +typedef struct { int top, left, bottom, right; } Insets; + +struct Person { + int age; + Person(const Insets l) : age(l.top) {} +}; + +void test() { Person p({}); } diff --git a/infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp.dot new file mode 100644 index 000000000..490a4d1e2 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/constructors/constructor_struct_init_list.cpp.dot @@ -0,0 +1,24 @@ +digraph iCFG { +6 [label="6: DeclStmt \n *&SIL_init_list__n$0.top:int =0 [line 17]\n *&SIL_init_list__n$0.left:int =0 [line 17]\n *&SIL_init_list__n$0.bottom:int =0 [line 17]\n *&SIL_init_list__n$0.right:int =0 [line 17]\n _fun_Person_Person(&p:class Person *,&SIL_init_list__n$0:class Insets ) [line 17]\n NULLIFY(&SIL_init_list__n$0,false); [line 17]\n NULLIFY(&p,false); [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit test \n " color=yellow style=filled] + + +4 [label="4: Start test\nFormals: \nLocals: p:class Person SIL_init_list__n$0:class Insets \n DECLARE_LOCALS(&return,&p,&SIL_init_list__n$0); [line 17]\n " color=yellow style=filled] + + + 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,false); [line 14]\n NULLIFY(&this,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit Person_Person \n " color=yellow style=filled] + + +1 [label="1: Start Person_Person\nFormals: this:class Person * l:class Insets \nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/frontend/cpp/ConstructorsTest.java b/infer/tests/frontend/cpp/ConstructorsTest.java index 24c48ae11..0beaf02b6 100644 --- a/infer/tests/frontend/cpp/ConstructorsTest.java +++ b/infer/tests/frontend/cpp/ConstructorsTest.java @@ -64,4 +64,10 @@ public class ConstructorsTest { throws InterruptedException, IOException, InferException { frontendTest("default_field_init.cpp"); } + + @Test + public void testConstructorInitListDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("constructor_struct_init_list.cpp"); + } }