From fcb83a949f8ee6f1a512d6f3d960a6121307d27f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezgi=20=C3=87i=C3=A7ek?= Date: Tue, 8 May 2018 09:31:04 -0700 Subject: [PATCH] implement missing CXXInheritedCtorInitExpr Reviewed By: jvillard Differential Revision: D7859552 fbshipit-source-id: d7cc63b --- facebook-clang-plugins | 2 +- infer/src/clang/cTrans.ml | 48 ++++++++++++++----- .../initialization/inheriting_constructor.cpp | 18 +++++++ .../inheriting_constructor.cpp.dot | 39 +++++++++++++++ 4 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp create mode 100644 infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp.dot diff --git a/facebook-clang-plugins b/facebook-clang-plugins index 079dc15e1..ad20e6754 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit 079dc15e1f37204632c61a4c09d3f82f78d0b1b7 +Subproject commit ad20e6754fe46be0e2793a8c986dc4c7fc66c047 diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 143e2a614..b7d7e40d7 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -212,8 +212,24 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s (Exp.Lvar pvar, typ) + let get_forwarded_params trans_state sil_loc = + (* forward all parameters of constructor except this *) + let context = trans_state.context in + let pdesc = context.procdesc in + let attr = Procdesc.get_attributes pdesc in + let procname = Procdesc.get_proc_name pdesc in + attr.formals (* remove this, which should always be the first formal parameter *) + |> List.tl_exn + |> List.fold_left ~init:([], []) ~f: + (fun (forwarded_params, forwarded_init_exps) (formal, typ) -> + let pvar = Pvar.mk formal procname in + let id = Ident.create_fresh Ident.knormal in + ( (Exp.Var id, typ) :: forwarded_params + , Sil.Load (id, Exp.Lvar pvar, typ, sil_loc) :: forwarded_init_exps ) ) + + let create_call_instr trans_state (return_type: Typ.t) function_sil params_sil sil_loc call_flags - ~is_objc_method = + ~is_objc_method ~is_inherited_ctor = let ret_id_typ = (Ident.create_fresh Ident.knormal, return_type) in let ret_id', params, initd_exps, ret_exps = (* Assumption: should_add_return_param will return true only for struct types *) @@ -259,9 +275,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s , let i, t = ret_id_typ in [(Exp.Var i, t)] ) in - let call_instr = Sil.Call (ret_id', function_sil, params, sil_loc, call_flags) in + let forwarded_params, forwarded_init_instrs = + if is_inherited_ctor then get_forwarded_params trans_state sil_loc else ([], []) + in + let call_instr = + Sil.Call (ret_id', function_sil, params @ forwarded_params, sil_loc, call_flags) + in let call_instr' = Sil.add_with_block_parameters_flag call_instr in - {empty_res_trans with instrs= [call_instr']; exps= ret_exps; initd_exps} + {empty_res_trans with instrs= forwarded_init_instrs @ [call_instr']; exps= ret_exps; initd_exps} (** Given a captured var, return the instruction to assign it to a temp *) @@ -1048,7 +1069,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let is_call_to_block = objc_exp_of_type_block fun_exp_stmt in let call_flags = {CallFlags.default with CallFlags.cf_is_objc_block= is_call_to_block} in create_call_instr trans_state function_type sil_fe act_params sil_loc call_flags - ~is_objc_method:false + ~is_objc_method:false ~is_inherited_ctor:false in let nname = "Call " ^ Exp.to_string sil_fe in let all_res_trans = result_trans_subexprs @ [res_trans_call] in @@ -1059,7 +1080,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s and cxx_method_construct_call_trans trans_state_pri result_trans_callee params_stmt si - function_type is_cpp_call_virtual extra_res_trans = + function_type is_cpp_call_virtual extra_res_trans ~is_inherited_ctor = let context = trans_state_pri.context in let sil_loc = CLocation.get_sil_location si context in (* first for method address, second for 'this' expression and other parameters *) @@ -1091,7 +1112,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let call_flags = {CallFlags.default with CallFlags.cf_virtual= is_cpp_call_virtual} in let res_trans_call = create_call_instr trans_state_pri function_type sil_method actual_params sil_loc - call_flags ~is_objc_method:false + call_flags ~is_objc_method:false ~is_inherited_ctor in let nname = "Call " ^ Exp.to_string sil_method in let all_res_trans = result_trans_subexprs @ [res_trans_call; extra_res_trans] in @@ -1118,10 +1139,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let fn_type_no_ref = CType_decl.get_type_from_expr_info expr_info context.CContext.tenv in let function_type = add_reference_if_glvalue fn_type_no_ref expr_info in cxx_method_construct_call_trans trans_state_pri result_trans_callee params_stmt si - function_type is_cpp_call_virtual empty_res_trans + function_type is_cpp_call_virtual empty_res_trans ~is_inherited_ctor:false - and cxxConstructExpr_trans trans_state si params_stmt ei cxx_constr_info = + and cxxConstructExpr_trans trans_state si params_stmt ei cxx_constr_info ~is_inherited_ctor = let context = trans_state.context in let trans_state_pri = PriorityNode.try_claim_priority_node trans_state si in let sil_loc = CLocation.get_sil_location si context in @@ -1169,7 +1190,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s in let res_trans = cxx_method_construct_call_trans trans_state_pri res_trans_callee params_stmt si - (Typ.mk Tvoid) false extra_res_trans + (Typ.mk Tvoid) false extra_res_trans ~is_inherited_ctor in {res_trans with exps= extra_res_trans.exps} @@ -1192,7 +1213,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let is_cpp_call_virtual = res_trans_callee.is_cpp_call_virtual in if res_trans_callee.exps <> [] then cxx_method_construct_call_trans trans_state_pri res_trans_callee [] si' (Typ.mk Tvoid) - is_cpp_call_virtual empty_res_trans + is_cpp_call_virtual empty_res_trans ~is_inherited_ctor:false else empty_res_trans @@ -1294,7 +1315,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let method_sil = Exp.Const (Const.Cfun callee_name) in let res_trans_call = create_call_instr trans_state method_type method_sil subexpr_exprs sil_loc call_flags - ~is_objc_method:true + ~is_objc_method:true ~is_inherited_ctor:false in let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in let nname = "Message Call: " ^ selector in @@ -3130,6 +3151,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | CXXConstructExpr (stmt_info, stmt_list, expr_info, cxx_constr_info) | CXXTemporaryObjectExpr (stmt_info, stmt_list, expr_info, cxx_constr_info) -> cxxConstructExpr_trans trans_state stmt_info stmt_list expr_info cxx_constr_info + ~is_inherited_ctor:false + | CXXInheritedCtorInitExpr (stmt_info, stmt_list, expr_info, cxx_construct_inherited_expr_info) -> + cxxConstructExpr_trans trans_state stmt_info stmt_list expr_info + cxx_construct_inherited_expr_info ~is_inherited_ctor:true | ObjCMessageExpr (stmt_info, stmt_list, expr_info, obj_c_message_expr_info) -> objCMessageExpr_trans trans_state stmt_info obj_c_message_expr_info stmt_list expr_info | CompoundStmt (stmt_info, stmt_list) -> @@ -3350,7 +3375,6 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | AsTypeExpr _ | AtomicExpr _ | CXXFoldExpr _ - | CXXInheritedCtorInitExpr _ | CXXUnresolvedConstructExpr _ | CXXUuidofExpr _ | CUDAKernelCallExpr _ diff --git a/infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp b/infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp new file mode 100644 index 000000000..a4e8e7063 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018 - 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 A { + A(int) {} + void foo(){}; +}; + +struct B : A { + using A::A; +}; + +int main() { B b(5); } diff --git a/infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp.dot new file mode 100644 index 000000000..ae01968eb --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/initialization/inheriting_constructor.cpp.dot @@ -0,0 +1,39 @@ +/* @generated */ +digraph cfg { +"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: b:B \n DECLARE_LOCALS(&return,&b); [line 18, column 1]\n " color=yellow style=filled] + + + "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_3" ; +"main.fad58de7366495db4650cfefac2fcd61_2" [label="2: Exit main \n " color=yellow style=filled] + + +"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: DeclStmt \n n$0=_fun_B_A(&b:B*,5:int) [line 18, column 16]\n " shape="box"] + + + "main.fad58de7366495db4650cfefac2fcd61_3" -> "main.fad58de7366495db4650cfefac2fcd61_2" ; +"A#A#{14779048587651412014}.4ba2c6594c8960564bedc7b6cbdf6ae0_1" [label="1: Start A_A\nFormals: this:A* __param_0:int\nLocals: \n DECLARE_LOCALS(&return); [line 10, column 3]\n " color=yellow style=filled] + + + "A#A#{14779048587651412014}.4ba2c6594c8960564bedc7b6cbdf6ae0_1" -> "A#A#{14779048587651412014}.4ba2c6594c8960564bedc7b6cbdf6ae0_2" ; +"A#A#{14779048587651412014}.4ba2c6594c8960564bedc7b6cbdf6ae0_2" [label="2: Exit A_A \n " color=yellow style=filled] + + +"A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_1" [label="1: Start B_A\nFormals: this:B* __param_0:int\nLocals: \n DECLARE_LOCALS(&return); [line 15, column 12]\n " color=yellow style=filled] + + + "A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_1" -> "A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_3" ; +"A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_2" [label="2: Exit B_A \n " color=yellow style=filled] + + +"A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_3" [label="3: Constructor Init \n n$0=*&this:B* [line 15, column 12]\n n$2=*&__param_0:int [line 15, column 12]\n n$1=_fun_A_A(n$0:B*,n$2:int) [line 15, column 12]\n " shape="box"] + + + "A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_3" -> "A#B#{18258347749069050656}.8db05fedcc195ce779d29dca399277d8_2" ; +"foo#A#(11285596688767843576).de1b7dc3a8a24aa7cc49648c6a039113_1" [label="1: Start A_foo\nFormals: this:A*\nLocals: \n DECLARE_LOCALS(&return); [line 11, column 3]\n " color=yellow style=filled] + + + "foo#A#(11285596688767843576).de1b7dc3a8a24aa7cc49648c6a039113_1" -> "foo#A#(11285596688767843576).de1b7dc3a8a24aa7cc49648c6a039113_2" ; +"foo#A#(11285596688767843576).de1b7dc3a8a24aa7cc49648c6a039113_2" [label="2: Exit A_foo \n " color=yellow style=filled] + + +}