[objc frontend] Raise SelfClassException only inside ObjCMethodCallExpr nodes

Reviewed By: jvillard

Differential Revision: D7816329

fbshipit-source-id: 3b46ef5
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent d718275402
commit 038c0b92d4

@ -33,12 +33,6 @@ let protect ~f ~recover ~pp_context (trans_unit_ctx: CFrontend_config.translatio
ClangLogging.log_caught_exception trans_unit_ctx "IncorrectAssumption" e.position
e.source_range e.ast_node ;
log_and_recover ~print:true "Known incorrect assumption in the frontend: %s@\n" e.msg
| CTrans_utils.Self.SelfClassException e ->
(* FIXME(t21762295): we do not expect this to happen but it does *)
Some (Typ.Name.to_string e.class_name)
|> ClangLogging.log_caught_exception trans_unit_ctx "SelfClassException" e.position
e.source_range ;
log_and_recover ~print:true "Unexpected SelfClassException %a@\n" Typ.Name.pp e.class_name
| exn ->
let trace = Backtrace.get () in
IExn.reraise_if exn ~f:(fun () ->

@ -136,13 +136,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
when they are the first argument of method calls. In that case they are not translated as
expressions, but we take the type and create a static method call from it. This is done in
objcMessageExpr_trans. *)
let exec_with_self_exception f trans_state stmt =
try f trans_state stmt with Self.SelfClassException e ->
let typ = Typ.mk (Tstruct e.class_name) in
{ empty_res_trans with
exps=
[ ( Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact}
, Typ.mk (Tint IULong) ) ] }
let sizeof_expr_class class_name =
let typ = Typ.mk (Tstruct class_name) in
( Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact}
, Typ.mk (Tint IULong) )
let add_reference_if_glvalue (typ: Typ.t) expr_info =
@ -756,15 +753,15 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
CContext.add_block_static_var context procname (pvar, typ) ;
let var_exp = Exp.Lvar pvar in
let exps =
if Self.is_var_self pvar (CContext.is_objc_method context) then
if Self.is_var_self pvar (CContext.is_objc_method context) && CType.is_class typ then
let class_name = CContext.get_curr_class_typename stmt_info context in
if CType.is_class typ then
if trans_state.is_fst_arg_objc_method_call then
raise
(Self.SelfClassException
{class_name; position= __POS__; source_range= stmt_info.Clang_ast_t.si_source_range})
else
let typ = CType.add_pointer_to_typ (Typ.mk (Tstruct class_name)) in
[(var_exp, typ)]
let exp_typ = sizeof_expr_class class_name in
[exp_typ]
else [(var_exp, typ)]
in
L.(debug Capture Verbose) "@\n@\n PVAR ='%s'@\n@\n" (Pvar.to_string pvar) ;
@ -923,7 +920,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(* NOTE: we create a node only if required. In that case this node *)
(* becomes the successor of the nodes that may be created when *)
(* translating the operands. *)
let res_trans_e1 = exec_with_self_exception instruction trans_state' s1 in
let res_trans_e1 = instruction trans_state' s1 in
let (var_exp, var_exp_typ) as e1_with_typ =
extract_exp_from_list res_trans_e1.exps
"@\nWARNING: Missing LHS operand in BinOp. Returning -1. Fix needed...@\n"
@ -931,9 +928,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let trans_state'' = {trans_state' with var_exp_typ= Some e1_with_typ} in
let res_trans_e2 =
(* translation of s2 is done taking care of block special case *)
exec_with_block_priority_exception
(exec_with_self_exception instruction)
trans_state'' s2 stmt_info
exec_with_block_priority_exception instruction trans_state'' s2 stmt_info
in
let e2_with_typ =
extract_exp_from_list res_trans_e2.exps
@ -1015,7 +1010,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(* afterwards. The 'instructions' function does not do that *)
let trans_state_param = {trans_state_pri with succ_nodes= []; var_exp_typ= None} in
let result_trans_subexprs =
let instruction' = exec_with_self_exception (exec_with_glvalue_as_reference instruction) in
let instruction' = exec_with_glvalue_as_reference instruction in
let res_trans_p = List.map ~f:(instruction' trans_state_param) params_stmt in
res_trans_callee :: res_trans_p
in
@ -1075,7 +1070,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
parameter and collect the results afterwards. The 'instructions' function does not do that *)
let result_trans_subexprs =
let trans_state_param = {trans_state_pri with succ_nodes= []; var_exp_typ= None} in
let instruction' = exec_with_self_exception (exec_with_glvalue_as_reference instruction) in
let instruction' = exec_with_glvalue_as_reference instruction in
let res_trans_p = List.map ~f:(instruction' trans_state_param) params_stmt in
result_trans_callee :: res_trans_p
in
@ -1204,12 +1199,15 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
CMethod_trans.get_class_name_method_call_from_receiver_kind context obj_c_message_expr_info
act_params
in
(* alloc or new *)
(* FIXME(t21762295): we do not expect this to propagate to the top but it does *)
raise
(Self.SelfClassException
{class_name; position= __POS__; source_range= si.Clang_ast_t.si_source_range})
if trans_state.is_fst_arg_objc_method_call then
raise
(Self.SelfClassException
{class_name; position= __POS__; source_range= si.Clang_ast_t.si_source_range})
else
let exp, typ = sizeof_expr_class class_name in
Some {empty_res_trans with exps= [(exp, typ)]}
else if
(* alloc or new *)
String.equal selector CFrontend_config.alloc
|| String.equal selector CFrontend_config.new_str
then
@ -1232,7 +1230,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| stmt :: rest ->
let obj_c_message_expr_info, fst_res_trans =
try
let fst_res_trans = instruction trans_state_param stmt in
let trans_state_param' = {trans_state_param with is_fst_arg_objc_method_call= true} in
let fst_res_trans = instruction trans_state_param' stmt in
(obj_c_message_expr_info, fst_res_trans)
with Self.SelfClassException e ->
let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in
@ -1242,7 +1241,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
in
(obj_c_message_expr_info, empty_res_trans)
in
let instruction' = exec_with_self_exception (exec_with_glvalue_as_reference instruction) in
let instruction' = exec_with_glvalue_as_reference instruction in
let l = List.map ~f:(instruction' trans_state_param) rest in
(obj_c_message_expr_info, fst_res_trans :: l)
| [] ->
@ -2208,9 +2207,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let trans_state' =
{trans_state_pri with succ_nodes= []; var_exp_typ= Some var_exp_typ}
in
let instruction' =
exec_with_self_exception (exec_with_glvalue_as_reference instruction)
in
let instruction' = exec_with_glvalue_as_reference instruction in
exec_with_block_priority_exception instruction' trans_state' ie var_stmt_info
in
let sil_e1', ie_typ =
@ -2496,7 +2493,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let trans_state' =
{trans_state_pri with succ_nodes= []; var_exp_typ= Some (ret_exp, ret_typ)}
in
let res_trans_stmt = exec_with_self_exception instruction trans_state' stmt in
let res_trans_stmt = instruction trans_state' stmt in
let sil_expr, _ =
extract_exp_from_list res_trans_stmt.exps
"WARNING: There should be only one return expression.@\n"
@ -2806,7 +2803,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let param = match stmt_list with [p] -> p | _ -> assert false in
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in
let trans_state_param = {trans_state_pri with succ_nodes= []} in
let result_trans_param = exec_with_self_exception instruction trans_state_param param in
let result_trans_param = instruction trans_state_param param in
let exp =
extract_exp_from_list result_trans_param.exps
"WARNING: There should be one expression to delete. @\n"
@ -3505,27 +3502,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
and expression_trans context stmt warning =
let trans_state =
{ context
; succ_nodes= []
; continuation= None
; priority= Free
; var_exp_typ= None
; opaque_exp= None }
in
let trans_state = CTrans_utils.default_trans_state context in
let res_trans_stmt = instruction trans_state stmt in
fst (CTrans_utils.extract_exp_from_list res_trans_stmt.exps warning)
let instructions_trans context body extra_instrs exit_node ~is_destructor_wrapper =
let trans_state =
{ context
; succ_nodes= [exit_node]
; continuation= None
; priority= Free
; var_exp_typ= None
; opaque_exp= None }
in
let default_trans_state = CTrans_utils.default_trans_state context in
let trans_state = {default_trans_state with succ_nodes= [exit_node]} in
let procname = Procdesc.get_proc_name context.CContext.procdesc in
let is_destructor =
match procname with

@ -137,7 +137,8 @@ type trans_state =
; continuation: continuation option (** current continuation *)
; priority: priority_node
; var_exp_typ: (Exp.t * Typ.t) option
; opaque_exp: (Exp.t * Typ.t) option }
; opaque_exp: (Exp.t * Typ.t) option
; is_fst_arg_objc_method_call: bool }
(** A translation result. It is returned by the translation function. *)
type trans_result =
@ -153,6 +154,16 @@ let empty_res_trans =
{root_nodes= []; leaf_nodes= []; instrs= []; exps= []; initd_exps= []; is_cpp_call_virtual= false}
let default_trans_state context =
{ context
; succ_nodes= []
; continuation= None
; priority= Free
; var_exp_typ= None
; opaque_exp= None
; is_fst_arg_objc_method_call= false }
let undefined_expression () = Exp.Var (Ident.create_fresh Ident.knormal)
(** Collect the results of translating a list of instructions, and link up the nodes created. *)

@ -27,7 +27,8 @@ type trans_state =
; continuation: continuation option (** current continuation *)
; priority: priority_node
; var_exp_typ: (Exp.t * Typ.t) option
; opaque_exp: (Exp.t * Typ.t) option }
; opaque_exp: (Exp.t * Typ.t) option
; is_fst_arg_objc_method_call: bool }
(** A translation result. It is returned by the translation function. *)
type trans_result =
@ -41,6 +42,8 @@ type trans_result =
val empty_res_trans : trans_result
val default_trans_state : CContext.t -> trans_state
val undefined_expression : unit -> Exp.t
val collect_res_trans : Procdesc.t -> trans_result list -> trans_result

@ -97,4 +97,14 @@
} else
return 0;
}
Class foo();
BOOL class_method_in_conditional() {
Class c = foo();
if ([c class]) {
return YES;
}
return NO;
}
@end

@ -1,5 +1,37 @@
/* @generated */
digraph cfg {
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_1" [label="1: Start class_method_in_conditional\nFormals: \nLocals: c:objc_class* \n DECLARE_LOCALS(&return,&c); [line 103, column 1]\n " color=yellow style=filled]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_1" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_8" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_2" [label="2: Exit class_method_in_conditional \n " color=yellow style=filled]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_3" [label="3: Return Stmt \n *&return:_Bool=0 [line 108, column 3]\n " shape="box"]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_3" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_2" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_4" [label="4: + \n " ]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_4" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_3" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_5" [label="5: Prune (true branch, if) \n PRUNE(sizeof(t=objc_class), true); [line 105, column 7]\n " shape="invhouse"]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_5" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_7" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_6" [label="6: Prune (false branch, if) \n PRUNE(!sizeof(t=objc_class), false); [line 105, column 7]\n " shape="invhouse"]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_6" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_4" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_7" [label="7: Return Stmt \n *&return:_Bool=1 [line 106, column 5]\n " shape="box"]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_7" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_2" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_8" [label="8: DeclStmt \n n$1=_fun_foo() [line 104, column 13]\n *&c:objc_class*=n$1 [line 104, column 3]\n " shape="box"]
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_8" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_5" ;
"class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_8" -> "class_method_in_conditional.2a19b0bd8eafdb3235f52585a49ef84a_6" ;
"b_m#B#class.82af96ad418803b2f96fc1bfa1572c10_1" [label="1: Start B_b_m\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 20, column 1]\n " color=yellow style=filled]
@ -172,16 +204,16 @@ digraph cfg {
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_4" -> "used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_2" ;
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_5" [label="5: BinaryOperatorStmt: NE \n n$15=*&c:objc_class* [line 95, column 15]\n " shape="box"]
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_5" [label="5: BinaryOperatorStmt: NE \n n$15=*sizeof(t=A):objc_class* [line 95, column 7]\n n$16=*&c:objc_class* [line 95, column 15]\n " shape="box"]
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_5" -> "used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_6" ;
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_5" -> "used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_7" ;
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_6" [label="6: Prune (true branch, if) \n PRUNE((sizeof(t=A) != n$15), true); [line 95, column 7]\n " shape="invhouse"]
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_6" [label="6: Prune (true branch, if) \n PRUNE((n$15 != n$16), true); [line 95, column 7]\n " shape="invhouse"]
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_6" -> "used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_8" ;
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_7" [label="7: Prune (false branch, if) \n PRUNE(!(sizeof(t=A) != n$15), false); [line 95, column 7]\n " shape="invhouse"]
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_7" [label="7: Prune (false branch, if) \n PRUNE(!(n$15 != n$16), false); [line 95, column 7]\n " shape="invhouse"]
"used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_7" -> "used_in_binary_op:#A#class.9f855a338b344f4b5060d2d4a2a955ed_9" ;

Loading…
Cancel
Save