Use clang for default argument resolution

Summary:
public
Simplify our frontend by using information from clang.
It will also make default argument resolution more robust
with templates

Reviewed By: jvillard

Differential Revision: D2890451

fb-gh-sync-id: 9db4beb
master
Andrzej Kotulski 9 years ago committed by facebook-github-bot-5
parent 10286931ee
commit b08acedf29

@ -1 +1 @@
Subproject commit cb65aec893159e2cf4d74ce4dae68f0b3513f065
Subproject commit df8dc4e093b0f8147e5d8dc06e3e5316ceac865a

@ -747,8 +747,7 @@ struct
(* verbatim from a call to a different function, and they might be side-effecting *)
(Procname.to_string pn) <> CFrontend_config.builtin_object_size
| _ -> true in
let params_stmt = if should_translate_args then
CTrans_utils.assign_default_params params_stmt fun_exp_stmt
let params_stmt = if should_translate_args then params_stmt
else [] in
let result_trans_subexprs =
let instruction' = exec_with_self_exception (exec_with_lvalue_as_reference instruction) in
@ -846,7 +845,7 @@ struct
(* CXXOperatorCallExpr: First stmt is method/function deref without this expr and the *)
(* rest are params, possibly including 'this' *)
let fun_exp_stmt, params_stmt = (match stmt_list with
| fe :: params -> fe, assign_default_params params fe
| fe :: params -> fe, params
| _ -> assert false) in
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state si in
(* claim priority if no ancestors has claimed priority before *)
@ -857,33 +856,28 @@ struct
cxx_method_construct_call_trans trans_state_pri result_trans_callee params_stmt
si function_type
and cxxConstructExpr_trans trans_state expr =
match expr with
| Clang_ast_t.CXXConstructExpr (si, params_stmt, ei, cxx_constr_info)
| Clang_ast_t.CXXTemporaryObjectExpr (si, params_stmt, ei, cxx_constr_info) ->
let context = trans_state.context in
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state si in
let decl_ref = cxx_constr_info.Clang_ast_t.xcei_decl_ref in
let class_type = CTypes_decl.get_type_from_expr_info ei context.CContext.tenv in
let this_type = Sil.Tptr (class_type, Sil.Pk_pointer) in
let var_exp = match trans_state.var_exp with
| Some e -> e
| None ->
let tenv = trans_state.context.CContext.tenv in
let procdesc = trans_state.context.CContext.procdesc in
let pvar = mk_temp_sil_var tenv procdesc "__temp_construct_" in
Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, class_type)];
Sil.Lvar pvar in
let this_res_trans = { empty_res_trans with
exps = [(var_exp, this_type)];
initd_exps = [var_exp];
} in
let res_trans_callee = decl_ref_trans trans_state this_res_trans si ei decl_ref in
let params_stmt' = assign_default_params params_stmt expr in
let res_trans = cxx_method_construct_call_trans trans_state_pri res_trans_callee
params_stmt' si Sil.Tvoid in
{ res_trans with exps = [(var_exp, class_type)] }
| _ -> assert false
and cxxConstructExpr_trans trans_state si params_stmt ei cxx_constr_info =
let context = trans_state.context in
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state si in
let decl_ref = cxx_constr_info.Clang_ast_t.xcei_decl_ref in
let class_type = CTypes_decl.get_type_from_expr_info ei context.CContext.tenv in
let this_type = Sil.Tptr (class_type, Sil.Pk_pointer) in
let var_exp = match trans_state.var_exp with
| Some e -> e
| None ->
let tenv = trans_state.context.CContext.tenv in
let procdesc = trans_state.context.CContext.procdesc in
let pvar = mk_temp_sil_var tenv procdesc "__temp_construct_" in
Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, class_type)];
Sil.Lvar pvar in
let this_res_trans = { empty_res_trans with
exps = [(var_exp, this_type)];
initd_exps = [var_exp];
} in
let res_trans_callee = decl_ref_trans trans_state this_res_trans si ei decl_ref in
let res_trans = cxx_method_construct_call_trans trans_state_pri res_trans_callee
params_stmt si Sil.Tvoid in
{ res_trans with exps = [(var_exp, class_type)] }
and cxx_destructor_call_trans trans_state si this_res_trans class_type_ptr =
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state si in
@ -1974,6 +1968,10 @@ struct
stmt_info all_res_trans in
{ res_trans_to_parent with exps = [(res_ex, cast_type)] }
and cxxDefaultArgExpr_trans trans_state default_arg_info =
match default_arg_info.Clang_ast_t.xdaei_init_expr with
| Some exp -> instruction trans_state exp
| None -> assert false
(* Translates a clang instruction into SIL instructions. It takes a *)
(* a trans_state containing current info on the translation and it returns *)
@ -2010,8 +2008,9 @@ struct
| CXXOperatorCallExpr(stmt_info, stmt_list, ei) ->
callExpr_trans trans_state stmt_info stmt_list ei
| CXXConstructExpr _ | CXXTemporaryObjectExpr _ ->
cxxConstructExpr_trans trans_state instr
| 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
| ObjCMessageExpr(stmt_info, stmt_list, expr_info, obj_c_message_expr_info) ->
if is_block_enumerate_function obj_c_message_expr_info then
@ -2208,6 +2207,9 @@ struct
| CXXDynamicCastExpr (stmt_info, stmts, expr_info, cast_expr_info, type_ptr, _) ->
cxxDynamicCastExpr_trans trans_state stmt_info stmts type_ptr
| CXXDefaultArgExpr (stmt_info, stmt_list, expr_info, default_arg_info) ->
cxxDefaultArgExpr_trans trans_state default_arg_info
| s -> (Printing.log_stats
"\n!!!!WARNING: found statement %s. \nACTION REQUIRED: Translation need to be defined. Statement ignored.... \n"
(Ast_utils.string_of_stmt s);

@ -652,53 +652,5 @@ let get_decl_pointer decl_ref_expr_info =
| Some decl_ref -> decl_ref.Clang_ast_t.dr_decl_pointer
| None -> assert false
let rec pointer_of_call_expr stmt =
let open Clang_ast_t in
match stmt with
| DeclRefExpr(_, _, _, decl_ref_expr_info) ->
Some (get_decl_pointer decl_ref_expr_info)
| MemberExpr(_, _, _, member_expr_info) ->
let decl_ref = member_expr_info.Clang_ast_t.mei_decl_ref in
Some decl_ref.Clang_ast_t.dr_decl_pointer
| CXXConstructExpr (_, _, _, cxx_construct_expr_info)
| CXXTemporaryObjectExpr (_, _, _, cxx_construct_expr_info) ->
let decl_ref = cxx_construct_expr_info.xcei_decl_ref in
Some decl_ref.Clang_ast_t.dr_decl_pointer
| _ ->
match snd (Clang_ast_proj.get_stmt_tuple stmt) with
| [stmt] -> pointer_of_call_expr stmt
| _ -> None
let get_decl_from_call_expr stmt =
match pointer_of_call_expr stmt with
| Some pointer -> Ast_utils.get_decl pointer
| _ -> None
let assign_default_params params_stmt call_stmt =
let open Clang_ast_t in
match get_decl_from_call_expr call_stmt with
| Some FunctionDecl (_, name_info, _, fdecl_info)
| Some CXXMethodDecl (_, name_info, _, fdecl_info, _)
| Some CXXConversionDecl (_, name_info, _, fdecl_info, _)
| Some CXXConstructorDecl (_, name_info, _, fdecl_info, _) ->
(let get_param_default_val param_decl = match param_decl with
| ParmVarDecl (_, _, _, var_decl_info) -> var_decl_info.vdi_init_expr
| _ -> None in
let replace_default_arg param = match param with
| CXXDefaultArgExpr _, Some default_expr -> default_expr
| instr, _ -> instr in
let default_params = IList.map get_param_default_val fdecl_info.Clang_ast_t.fdi_parameters in
try
let param_args = IList.combine params_stmt default_params in
IList.map replace_default_arg param_args
with Invalid_argument _ ->
let name = name_info.ni_name in
(* IList.combine failed because of different list lengths *)
Printing.log_err "Param count doesn't match %s\n" name;
params_stmt)
| Some _ -> params_stmt
| None -> params_stmt
let is_block_enumerate_function mei =
mei.Clang_ast_t.omei_selector = CFrontend_config.enumerateObjectsUsingBlock

@ -211,8 +211,4 @@ val is_logical_negation_of_int : Sil.tenv -> Clang_ast_t.expr_info -> Clang_ast_
val is_dispatch_function : Clang_ast_t.stmt list -> int option
val assign_default_params : Clang_ast_t.stmt list -> Clang_ast_t.stmt -> Clang_ast_t.stmt list
val is_block_enumerate_function : Clang_ast_t.obj_c_message_expr_info -> bool
val pointer_of_call_expr : Clang_ast_t.stmt -> Clang_ast_t.pointer option

Loading…
Cancel
Save