[clang] distinguish genuine internal failures from unimplemented features

Summary:
The clang frontend uses `assert false` for unimplemented features that should
abort method translations, as well as for genuine internal errors.
Distinguishing between the two, we can fail hard on the latter and not the
former.

1. This introduces a new exception `Unimplemented` that is used instead of `assert false` where appropriate.
2. Changed some other cases into `die ...` (when there's an error message to display)
3. Wherever a path in the code that we assumed to be unreachable was observed reachable, we now raise `IncorrectAssumption`. These should be fixed, but the fixes are not obvious.

Reviewed By: sblackshear

Differential Revision: D5784384

fbshipit-source-id: 61b55af
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent faf04af1f4
commit 2fff3b0733

@ -138,6 +138,8 @@ let elapsed_time fmt () =
let string fmt s = F.fprintf fmt "%s" s let string fmt s = F.fprintf fmt "%s" s
let option pp fmt = function None -> string fmt "None" | Some x -> F.fprintf fmt "Some %a" pp x
let to_string ~f fmt x = string fmt (f x) let to_string ~f fmt x = string fmt (f x)
let pp_argfile fmt fname = let pp_argfile fmt fname =

@ -68,6 +68,8 @@ val latex : color -> env
val color_string : color -> string val color_string : color -> string
(** string representation of colors *) (** string representation of colors *)
val option : (F.formatter -> 'a -> unit) -> F.formatter -> 'a option -> unit
val string : F.formatter -> string -> unit val string : F.formatter -> string -> unit
val cli_args : F.formatter -> string list -> unit val cli_args : F.formatter -> string list -> unit

@ -15,25 +15,13 @@ let debug_mode = Config.debug_mode || Config.frontend_stats
let buffer_len = 262143 let buffer_len = 262143
let catch_biniou_buffer_errors f x =
try[@warning "-52"] f x
with
| Invalid_argument
(* suppress warning: allow this one case because we're just reraising the error with another
error message so it doesn't really matter if this eventually fails *)
"Bi_inbuf.refill_from_channel"
->
L.external_error "WARNING: biniou buffer too short, skipping the file@\n" ;
assert false
(* This function reads the json file in fname, validates it, and encoded in the AST data structure (* This function reads the json file in fname, validates it, and encoded in the AST data structure
defined in Clang_ast_t. *) defined in Clang_ast_t. *)
let validate_decl_from_file fname = let validate_decl_from_file fname =
catch_biniou_buffer_errors (Ag_util.Biniou.from_file ~len:buffer_len Clang_ast_b.read_decl) fname Ag_util.Biniou.from_file ~len:buffer_len Clang_ast_b.read_decl fname
let validate_decl_from_channel chan = let validate_decl_from_channel chan =
catch_biniou_buffer_errors (Ag_util.Biniou.from_channel ~len:buffer_len Clang_ast_b.read_decl) Ag_util.Biniou.from_channel ~len:buffer_len Clang_ast_b.read_decl chan
chan
let register_perf_stats_report source_file = let register_perf_stats_report source_file =
let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in

@ -229,7 +229,8 @@ let make_next_object_exp stmt_info item items =
let decl_ref_expr_info = make_decl_ref_expr_info decl_ref in let decl_ref_expr_info = make_decl_ref_expr_info decl_ref in
(Clang_ast_t.DeclRefExpr (stmt_info_var, [], expr_info, decl_ref_expr_info), var_qual_type) (Clang_ast_t.DeclRefExpr (stmt_info_var, [], expr_info, decl_ref_expr_info), var_qual_type)
| _ | _
-> assert false -> CFrontend_config.incorrect_assumption "unexpected item %a"
(Pp.to_string ~f:Clang_ast_j.string_of_stmt) item
in in
let message_call = let message_call =
make_message_expr create_id_type CFrontend_config.next_object items stmt_info false make_message_expr create_id_type CFrontend_config.next_object items stmt_info false
@ -582,7 +583,10 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
; free_stop ] ; free_stop ]
, op ) , op )
| _ | _
-> assert false -> (* FIXME(t21762295) this is reachable *)
CFrontend_config.incorrect_assumption "wrong params in block enumerate translation: %a"
(Pp.seq (Pp.to_string ~f:Clang_ast_j.string_of_decl))
params
in in
let open Clang_ast_t in let open Clang_ast_t in
match stmt_list with match stmt_list with

@ -301,7 +301,6 @@ let do_frontend_checks (trans_unit_ctx: CFrontend_config.translation_unit_contex
"Loading the following linters files: %a@\n" (Pp.comma_seq Format.pp_print_string) "Loading the following linters files: %a@\n" (Pp.comma_seq Format.pp_print_string)
linters_files ; linters_files ;
CTL.create_ctl_evaluation_tracker trans_unit_ctx.source_file ; CTL.create_ctl_evaluation_tracker trans_unit_ctx.source_file ;
try
let parsed_linters = parse_ctl_files linters_files in let parsed_linters = parse_ctl_files linters_files in
let filtered_parsed_linters = let filtered_parsed_linters =
CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file
@ -329,8 +328,5 @@ let do_frontend_checks (trans_unit_ctx: CFrontend_config.translation_unit_contex
L.(debug Linters Medium) "End linting file %a@\n" SourceFile.pp source_file ; L.(debug Linters Medium) "End linting file %a@\n" SourceFile.pp source_file ;
CTL.save_dotty_when_in_debug_mode trans_unit_ctx.CFrontend_config.source_file CTL.save_dotty_when_in_debug_mode trans_unit_ctx.CFrontend_config.source_file
| _ | _
-> assert false -> (* NOTE: Assumes that an AST always starts with a TranslationUnitDecl *)
(* NOTE: Assumes that an AST always starts with a TranslationUnitDecl *) assert false
with Assert_failure (file, line, column) as exn ->
L.internal_error "Fatal error: exception Assert_failure(%s, %d, %d)@\n%!" file line column ;
reraise exn

@ -8,9 +8,18 @@
*) *)
open! IStd open! IStd
module F = Format
(** Module that contains constants and global state used in the frontend *) (** Module that contains constants and global state used in the frontend *)
exception IncorrectAssumption of string
let incorrect_assumption fmt = F.kasprintf (fun msg -> raise (IncorrectAssumption msg)) fmt
exception Unimplemented of string
let unimplemented fmt = F.kasprintf (fun msg -> raise (Unimplemented msg)) fmt
type clang_lang = C | CPP | ObjC | ObjCPP [@@deriving compare] type clang_lang = C | CPP | ObjC | ObjCPP [@@deriving compare]
let equal_clang_lang = [%compare.equal : clang_lang] let equal_clang_lang = [%compare.equal : clang_lang]

@ -11,6 +11,18 @@ open! IStd
(** Module that contains constants and global state used in the frontend *) (** Module that contains constants and global state used in the frontend *)
exception IncorrectAssumption of string
val incorrect_assumption : ('a, Format.formatter, unit, _) format4 -> 'a
(** Used to mark places in the frontend that incorrectly assume something to be
impossible. TODO(t21762295) get rid of all instances of this. *)
exception Unimplemented of string
val unimplemented : ('a, Format.formatter, unit, _) format4 -> 'a
(** Raise Unimplemented. This is caught at the level of translating a method and makes the frontend
give up on that method. *)
type clang_lang = C | CPP | ObjC | ObjCPP [@@deriving compare] type clang_lang = C | CPP | ObjC | ObjCPP [@@deriving compare]
val equal_clang_lang : clang_lang -> clang_lang -> bool val equal_clang_lang : clang_lang -> clang_lang -> bool

@ -19,12 +19,14 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron
(* Translates the method/function's body into nodes of the cfg. *) (* Translates the method/function's body into nodes of the cfg. *)
let add_method trans_unit_ctx tenv cg cfg class_decl_opt procname body has_return_param let add_method trans_unit_ctx tenv cg cfg class_decl_opt procname body has_return_param
is_objc_method outer_context_opt extra_instrs = is_objc_method outer_context_opt extra_instrs =
let handle_translation_failure () = L.(debug Capture Verbose)
"@\n@\n>>---------- ADDING METHOD: '%a' ---------<<@\n@\n" Typ.Procname.pp procname ;
let handle_frontend_failure ~print fmt =
Cfg.remove_proc_desc cfg procname ; Cfg.remove_proc_desc cfg procname ;
CMethod_trans.create_external_procdesc cfg procname is_objc_method None CMethod_trans.create_external_procdesc cfg procname is_objc_method None ;
(if print then L.internal_error else L.(debug Capture Quiet))
("Aborting translation of method '%a':@\n" ^^ fmt) Typ.Procname.pp procname
in in
L.(debug Capture Verbose)
"@\n@\n>>---------- ADDING METHOD: '%s' ---------<<@\n@." (Typ.Procname.to_string procname) ;
try try
match Cfg.find_proc_desc_from_name cfg procname with match Cfg.find_proc_desc_from_name cfg procname with
| Some procdesc | Some procdesc
@ -48,22 +50,21 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron
| None | None
-> () -> ()
with with
| Not_found (* Always keep going in case of known limitations of the frontend, crash otherwise (by not
-> () catching the exception) unless `--keep-going` was passed. Print errors we should fix
| CTrans_utils.Self.SelfClassException _ (t21762295) to the console. *)
-> (* this shouldn't happen, because self or [a class] should always be arguments of | CFrontend_config.Unimplemented msg
functions. This is to make sure I'm not wrong. *) -> handle_frontend_failure ~print:false "Unimplemented feature:@\n %s@\n" msg
assert false | CFrontend_config.IncorrectAssumption msg
| CTrans_utils.TemplatedCodeException _ -> (* FIXME(t21762295): we do not expect this to happen but it does *)
-> L.internal_error "Fatal error: frontend doesn't support translation of templated code@\n" ; handle_frontend_failure ~print:true "Known incorrect assumption in the frontend: %s@\n" msg
handle_translation_failure () | CTrans_utils.Self.SelfClassException class_name
| CTrans_utils.UnsupportedStatementException stmt when Config.keep_going -> (* FIXME(t21762295): we do not expect this to happen but it does *)
-> L.internal_error "Unimplemented: translation for statement %s" handle_frontend_failure ~print:true "Unexpected SelfClassException %a@\n" Typ.Name.pp
(Clang_ast_proj.get_stmt_kind_string stmt) ; class_name
handle_translation_failure () | exn when Config.keep_going
| Assert_failure (file, line, column) when Config.keep_going -> handle_frontend_failure ~print:true "Frontend error: %a@\nBacktrace:@\n%s" Exn.pp exn
-> L.internal_error "Fatal error: exception Assert_failure(%s, %d, %d)@\n%!" file line column ; (Exn.backtrace ())
handle_translation_failure ()
let function_decl trans_unit_ctx tenv cfg cg func_decl block_data_opt = let function_decl trans_unit_ctx tenv cfg cg func_decl block_data_opt =
let captured_vars, outer_context_opt = let captured_vars, outer_context_opt =

@ -118,8 +118,7 @@ let evaluate_place_holder context ph an =
| "%name%" | "%name%"
-> MF.monospaced_to_string (Ctl_parser_types.ast_node_name an) -> MF.monospaced_to_string (Ctl_parser_types.ast_node_name an)
| _ | _
-> L.internal_error "ERROR: helper function %s is unknown. Stop.@\n" ph ; -> L.die InternalError "helper function %s is unknown" ph
assert false
(* given a message this function searches for a place-holder identifier, (* given a message this function searches for a place-holder identifier,
eg %id%. Then it evaluates id and replaces %id% in message eg %id%. Then it evaluates id and replaces %id% in message
@ -156,8 +155,7 @@ let string_to_err_kind = function
| "LIKE" | "LIKE"
-> Exceptions.Klike -> Exceptions.Klike
| s | s
-> L.internal_error "@\n[ERROR] Severity %s does not exist. Stop.@\n" s ; -> L.die InternalError "Severity %s does not exist" s
assert false
let string_to_issue_mode m = let string_to_issue_mode m =
match m with match m with
@ -166,8 +164,7 @@ let string_to_issue_mode m =
| "OFF" | "OFF"
-> CIssue.Off -> CIssue.Off
| s | s
-> L.internal_error "@\n[ERROR] Mode %s does not exist. Please specify ON/OFF@\n" s ; -> L.die InternalError "Mode %s does not exist. Please specify ON/OFF" s
assert false
let post_process_linter_definition (linter: linter) = let post_process_linter_definition (linter: linter) =
match match

@ -656,19 +656,13 @@ let get_procname_from_cpp_lambda context dec =
-> let name_info, decl_ptr, _ = CAst_utils.get_info_from_decl_ref dr in -> let name_info, decl_ptr, _ = CAst_utils.get_info_from_decl_ref dr in
create_procdesc_with_pointer context decl_ptr None name_info.ni_name create_procdesc_with_pointer context decl_ptr None name_info.ni_name
| _ | _
-> (* We should not get here *) assert false ) -> assert false )
| _ | _
-> (* We should not get here *) assert false -> assert false
let get_captures_from_cpp_lambda dec = let get_captures_from_cpp_lambda dec =
match dec with match dec with
| Clang_ast_t.CXXRecordDecl (_, _, _, _, _, _, _, cxx_rdi) | Clang_ast_t.CXXRecordDecl (_, _, _, _, _, _, _, cxx_rdi)
-> cxx_rdi.xrdi_lambda_captures -> cxx_rdi.xrdi_lambda_captures
| _ | _
-> (* We should not get here *) assert false -> assert false
(*
let instance_to_method_call_type instance =
if instance then MCVirtual
else MCStatic
*)

@ -59,7 +59,6 @@ type t =
| EH of ALVar.alexp list * t | EH of ALVar.alexp list * t
| ET of ALVar.alexp list * transitions option * t | ET of ALVar.alexp list * transitions option * t
let has_transition phi = let has_transition phi =
match phi with match phi with
| True | True
@ -609,7 +608,9 @@ let transition_decl_to_stmt d trs =
| InitExpr, CXXConstructorDecl _ | InitExpr, CXXConstructorDecl _
| InitExpr, CXXConversionDecl _ | InitExpr, CXXConversionDecl _
| InitExpr, CXXDestructorDecl _ | InitExpr, CXXDestructorDecl _
-> assert false (* to be done. Requires extending to lists *) -> (* requires extending to lists *)
CFrontend_config.unimplemented
"transition_decl_to_stmt: InitExpr/CXX{Method,Constructor,Conversion,Destructor}"
| InitExpr, EnumConstantDecl (_, _, _, ecdi) | InitExpr, EnumConstantDecl (_, _, _, ecdi)
-> ecdi.ecdi_init_expr -> ecdi.ecdi_init_expr
| _, _ | _, _

@ -454,7 +454,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let exps = [(exp, typ)] in let exps = [(exp, typ)] in
{empty_res_trans with exps; instrs} {empty_res_trans with exps; instrs}
| Tfun _ | Tvoid | Tarray _ | TVar _ | Tfun _ | Tvoid | Tarray _ | TVar _
-> assert false -> CFrontend_config.unimplemented "fill_typ_with_zero on type %a" (Typ.pp Pp.text) typ
in in
let res_trans = fill_typ_with_zero var_exp_typ in let res_trans = fill_typ_with_zero var_exp_typ in
{res_trans with initd_exps= [fst var_exp_typ]} {res_trans with initd_exps= [fst var_exp_typ]}
@ -572,9 +572,12 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
-> CType_decl.get_record_typename ~tenv:context.tenv decl -> CType_decl.get_record_typename ~tenv:context.tenv decl
| _ | _
-> assert false ) -> assert false )
| _ | _ as decl
-> assert false -> (* FIXME(t21762295): we do not expect this to happen but it does *)
(* di_parent_pointer should be always set for fields/ivars *) CFrontend_config.incorrect_assumption
"di_parent_pointer should be always set for fields/ivars, but got %a"
(Pp.option (Pp.to_string ~f:Clang_ast_j.string_of_decl))
decl
in in
let field_name = CGeneral_utils.mk_class_field_name class_tname field_string in let field_name = CGeneral_utils.mk_class_field_name class_tname field_string in
let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in
@ -844,8 +847,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
match stmt_list with match stmt_list with
| [a; i] | [a; i]
-> (a, i) -> (a, i)
(* Assumption: the statement list contains 2 elements, (* Assumption: the statement list contains 2 elements, the first is the array expr and the
the first is the array expr and the second the index *) second the index *)
| _ | _
-> assert false -> assert false
(* Let's get notified if the assumption is wrong...*) (* Let's get notified if the assumption is wrong...*)
@ -1013,9 +1016,14 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let act_params = let act_params =
let params = List.tl_exn (collect_exprs result_trans_subexprs) in let params = List.tl_exn (collect_exprs result_trans_subexprs) in
if Int.equal (List.length params) (List.length params_stmt) then params if Int.equal (List.length params) (List.length params_stmt) then params
else ( else
L.internal_error "ERROR: stmt_list and res_trans_par.exps must have same size@\n" ; (* FIXME(t21762295) this is reachable *)
assert false ) CFrontend_config.incorrect_assumption
"In call to %a: stmt_list and res_trans_par.exps must have same size but they don't:@\nstmt_list(%d)=[%a]@\nres_trans_par.exps(%d)=[%a]@\n"
Typ.Procname.pp procname (List.length params) (Pp.seq Exp.pp)
(List.map ~f:fst params) (List.length params_stmt)
(Pp.seq (Pp.to_string ~f:Clang_ast_j.string_of_stmt))
params_stmt
in in
let act_params = let act_params =
if is_cf_retain_release then (Exp.Const (Const.Cint IntLit.one), Typ.mk (Tint Typ.IBool)) if is_cf_retain_release then (Exp.Const (Const.Cint IntLit.one), Typ.mk (Tint Typ.IBool))
@ -1050,16 +1058,20 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let context = trans_state_pri.context in let context = trans_state_pri.context in
let procname = Procdesc.get_proc_name context.procdesc in let procname = Procdesc.get_proc_name context.procdesc in
let sil_loc = CLocation.get_sil_location si context in let sil_loc = CLocation.get_sil_location si context in
(* first for method address, second for 'this' expression *) (* first for method address, second for 'this' expression and other parameters *)
assert (Int.equal (List.length result_trans_callee.exps) 2) ; assert (List.length result_trans_callee.exps >= 1) ;
let sil_method, _ = List.hd_exn result_trans_callee.exps in let sil_method, _ = List.hd_exn result_trans_callee.exps in
let callee_pname = let callee_pname =
match sil_method with Exp.Const Const.Cfun pn -> pn | _ -> assert false match sil_method with
(* method pointer not implemented, this shouldn't happen *) | Exp.Const Const.Cfun pn
-> pn
| _
-> (* method pointer not implemented, this shouldn't happen but it does (t21762295) *)
CFrontend_config.incorrect_assumption "Could not resolve CXX method call %a" Exp.pp
sil_method
in in
(* As we may have nodes coming from different parameters we need to *) (* As we may have nodes coming from different parameters we need to call instruction for each
(* call instruction for each parameter and collect the results *) parameter and collect the results afterwards. The 'instructions' function does not do that *)
(* afterwards. The 'instructions' function does not do that *)
let result_trans_subexprs = let result_trans_subexprs =
let trans_state_param = {trans_state_pri with succ_nodes= []; var_exp_typ= None} in 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_self_exception (exec_with_glvalue_as_reference instruction) in
@ -1175,7 +1187,9 @@ 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 CMethod_trans.get_class_name_method_call_from_receiver_kind context obj_c_message_expr_info
act_params act_params
in in
raise (Self.SelfClassException class_name) (* alloc or new *) (* alloc or new *)
(* FIXME(t21762295): we do not expect this to propagate to the top but it does *)
raise (Self.SelfClassException class_name)
else if String.equal selector CFrontend_config.alloc else if String.equal selector CFrontend_config.alloc
|| String.equal selector CFrontend_config.new_str || String.equal selector CFrontend_config.new_str
then then
@ -1489,8 +1503,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let root_nodes' = if root_nodes <> [] then root_nodes else op_res_trans.root_nodes in let root_nodes' = if root_nodes <> [] then root_nodes else op_res_trans.root_nodes in
{op_res_trans with root_nodes= root_nodes'} {op_res_trans with root_nodes= root_nodes'}
| _ | _
-> L.(debug Capture Medium) "BinaryConditionalOperator not translated@." ; -> CFrontend_config.unimplemented "BinaryConditionalOperator not translated"
assert false
(* Translate a condition for if/loops statement. It shorts-circuit and/or. *) (* Translate a condition for if/loops statement. It shorts-circuit and/or. *)
(* The invariant is that the translation of a condition always contains (at least) *) (* The invariant is that the translation of a condition always contains (at least) *)
@ -1810,7 +1823,11 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(* succ_nodes will remove the temps *) (* succ_nodes will remove the temps *)
{empty_res_trans with root_nodes= top_nodes; leaf_nodes= succ_nodes} {empty_res_trans with root_nodes= top_nodes; leaf_nodes= succ_nodes}
| _ | _
-> assert false -> (* TODO(t21762295) this raises sometimes *)
CFrontend_config.incorrect_assumption
"Unexpected Switch Statement sub-expression list: [%a]"
(Pp.semicolon_seq (Pp.to_string ~f:Clang_ast_j.string_of_stmt))
switch_stmt_list
and stmtExpr_trans trans_state stmt_list = and stmtExpr_trans trans_state stmt_list =
let stmt = let stmt =
@ -2058,7 +2075,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| Tint _ | Tfloat _ | Tptr _ | Tint _ | Tfloat _ | Tptr _
-> initListExpr_builtin_trans trans_state_pri init_stmt_info stmts var_exp var_typ -> initListExpr_builtin_trans trans_state_pri init_stmt_info stmts var_exp var_typ
| _ | _
-> assert false -> CFrontend_config.unimplemented "InitListExp for var %a of type %a" Exp.pp var_exp
(Typ.pp Pp.text) var_typ
in in
let nname = "InitListExp" in let nname = "InitListExp" in
let res_trans = let res_trans =
@ -2185,8 +2203,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| (RecordDecl _) :: var_decls' | (RecordDecl _) :: var_decls'
-> (* Record declaration is done in the beginning when procdesc is defined.*) -> (* Record declaration is done in the beginning when procdesc is defined.*)
collect_all_decl trans_state var_decls' next_nodes stmt_info collect_all_decl trans_state var_decls' next_nodes stmt_info
| _ | decl :: _
-> assert false -> CFrontend_config.incorrect_assumption "unexpected decl type %s in collect_all_decl: %a"
(Clang_ast_proj.get_decl_kind_string decl) (Pp.to_string ~f:Clang_ast_j.string_of_decl)
decl
(* stmt_list is ignored because it contains the same instructions as *) (* stmt_list is ignored because it contains the same instructions as *)
(* the init expression. We use the latter info. *) (* the init expression. We use the latter info. *)
@ -2196,15 +2216,19 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let open Clang_ast_t in let open Clang_ast_t in
match decl_list with match decl_list with
| (VarDecl _) :: _ | (VarDecl _) :: _
-> (* Case for simple variable declarations*) (* Case for simple variable declarations*)
collect_all_decl trans_state decl_list succ_nodes stmt_info | (CXXRecordDecl _) :: _
| (CXXRecordDecl _) :: _ (*C++/C record decl treated in the same way *) | (RecordDecl _) :: _ (*C++/C record decl treated in the same way *)
| (RecordDecl _) :: _
-> (* Case for struct *) -> (* Case for struct *)
collect_all_decl trans_state decl_list succ_nodes stmt_info collect_all_decl trans_state decl_list succ_nodes stmt_info
| _ | (TypedefDecl _) :: _ | (UsingDirectiveDecl _) :: _
-> L.(debug Capture Medium) -> empty_res_trans
"WARNING: In DeclStmt found an unknown declaration type. RETURNING empty list of declaration. NEED TO BE FIXED" ; | decl :: _
empty_res_trans -> CFrontend_config.unimplemented "In DeclStmt found an unknown declaration type %s"
(Clang_ast_j.string_of_decl decl)
| []
-> assert false
in in
{res_trans with leaf_nodes= []} {res_trans with leaf_nodes= []}
@ -2246,7 +2270,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
how x.f = a is actually implemented by the runtime.*) how x.f = a is actually implemented by the runtime.*)
and pseudoObjectExpr_trans trans_state stmt_list = and pseudoObjectExpr_trans trans_state stmt_list =
L.(debug Capture Verbose) L.(debug Capture Verbose)
" priority node free = '%s'@\n@." " priority node free = '%s'@\n@\n"
(string_of_bool (PriorityNode.is_priority_free trans_state)) ; (string_of_bool (PriorityNode.is_priority_free trans_state)) ;
let rec do_semantic_elements el = let rec do_semantic_elements el =
let open Clang_ast_t in let open Clang_ast_t in
@ -2906,9 +2930,15 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| NullStmt _, FallThroughAttr _ | NullStmt _, FallThroughAttr _
-> no_op_trans trans_state.succ_nodes -> no_op_trans trans_state.succ_nodes
| _ | _
-> assert false (* More cases to come. With the assert false we can find them *) ) -> CFrontend_config.unimplemented
"attributedStmt [stmt] [attr] with:@\nstmt=%s@\nattr=%s@\n"
(Clang_ast_j.string_of_stmt stmt) (Clang_ast_j.string_of_attribute attr) )
| _ | _
-> assert false -> CFrontend_config.unimplemented "attributedStmt with:@\nstmts=[%a]@\nattrs=[%a]@\n"
(Pp.semicolon_seq (Pp.to_string ~f:Clang_ast_j.string_of_stmt))
stmts
(Pp.semicolon_seq (Pp.to_string ~f:Clang_ast_j.string_of_attribute))
attrs
and breakStmt_trans trans_state stmt_info = and breakStmt_trans trans_state stmt_info =
match trans_state.continuation with match trans_state.continuation with
@ -2986,9 +3016,9 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| SwitchStmt (stmt_info, switch_stmt_list) | SwitchStmt (stmt_info, switch_stmt_list)
-> switchStmt_trans trans_state stmt_info switch_stmt_list -> switchStmt_trans trans_state stmt_info switch_stmt_list
| CaseStmt _ | CaseStmt _
-> L.(debug Capture Verbose) -> (* where do we even get case stmts outside of the switch stmt? (t21762295) *)
"FATAL: Passing from CaseStmt outside of SwitchStmt, terminating.@\n" ; CFrontend_config.incorrect_assumption "Case statement outside of switch statement: %a"
assert false (Pp.to_string ~f:Clang_ast_j.string_of_stmt) instr
| StmtExpr (_, stmt_list, _) | StmtExpr (_, stmt_list, _)
-> stmtExpr_trans trans_state stmt_list -> stmtExpr_trans trans_state stmt_list
| ForStmt (stmt_info, [init; decl_stmt; cond; incr; body]) | ForStmt (stmt_info, [init; decl_stmt; cond; incr; body])
@ -3167,9 +3197,105 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| SubstNonTypeTemplateParmExpr _ | SubstNonTypeTemplateParmExpr _
| SubstNonTypeTemplateParmPackExpr _ | SubstNonTypeTemplateParmPackExpr _
| CXXDependentScopeMemberExpr _ | CXXDependentScopeMemberExpr _
-> raise (CTrans_utils.TemplatedCodeException instr) -> raise
| s (CFrontend_config.unimplemented "Translation of templated code is unsupported: %a"
-> raise (CTrans_utils.UnsupportedStatementException s) (Pp.to_string ~f:Clang_ast_j.string_of_stmt) instr)
| ForStmt (_, _) | WhileStmt (_, _) | DoStmt (_, _) | ObjCForCollectionStmt (_, _)
-> assert false
| MSAsmStmt _
| CapturedStmt _
| CoreturnStmt _
| CoroutineBodyStmt _
| AddrLabelExpr _
| ArrayTypeTraitExpr _
| AsTypeExpr _
| AtomicExpr _
| CXXFoldExpr _
| CXXInheritedCtorInitExpr _
| CXXUnresolvedConstructExpr _
| CXXUuidofExpr _
| CUDAKernelCallExpr _
| ChooseExpr _
| ConvertVectorExpr _
| CoawaitExpr _
| CoyieldExpr _
| DependentCoawaitExpr _
| DependentScopeDeclRefExpr _
| DesignatedInitExpr _
| DesignatedInitUpdateExpr _
| ExpressionTraitExpr _
| FunctionParmPackExpr _
| ImaginaryLiteral _
| MSPropertyRefExpr _
| MSPropertySubscriptExpr _
| NoInitExpr _
| OMPArraySectionExpr _
| ObjCAvailabilityCheckExpr _
| ObjCIsaExpr _
| ObjCSubscriptRefExpr _
| UnresolvedLookupExpr _
| UnresolvedMemberExpr _
| PackExpansionExpr _
| ParenListExpr _
| TypoExpr _
| IndirectGotoStmt _
| MSDependentExistsStmt _
| OMPAtomicDirective _
| OMPBarrierDirective _
| OMPCancelDirective _
| OMPCancellationPointDirective _
| OMPCriticalDirective _
| OMPFlushDirective _
| OMPDistributeDirective _
| OMPDistributeParallelForDirective _
| OMPDistributeParallelForSimdDirective _
| OMPDistributeSimdDirective _
| OMPForDirective _
| OMPForSimdDirective _
| OMPParallelForDirective _
| OMPParallelForSimdDirective _
| OMPSimdDirective _
| OMPTargetParallelForSimdDirective _
| OMPTargetSimdDirective _
| OMPTargetTeamsDistributeDirective _
| OMPTargetTeamsDistributeParallelForDirective _
| OMPTargetTeamsDistributeParallelForSimdDirective _
| OMPTargetTeamsDistributeSimdDirective _
| OMPTaskLoopDirective _
| OMPTaskLoopSimdDirective _
| OMPTeamsDistributeDirective _
| OMPTeamsDistributeParallelForDirective _
| OMPTeamsDistributeParallelForSimdDirective _
| OMPTeamsDistributeSimdDirective _
| OMPMasterDirective _
| OMPOrderedDirective _
| OMPParallelDirective _
| OMPParallelSectionsDirective _
| OMPSectionDirective _
| OMPSectionsDirective _
| OMPSingleDirective _
| OMPTargetDataDirective _
| OMPTargetDirective _
| OMPTargetEnterDataDirective _
| OMPTargetExitDataDirective _
| OMPTargetParallelDirective _
| OMPTargetParallelForDirective _
| OMPTargetTeamsDirective _
| OMPTargetUpdateDirective _
| OMPTaskDirective _
| OMPTaskgroupDirective _
| OMPTaskwaitDirective _
| OMPTaskyieldDirective _
| OMPTeamsDirective _
| SEHExceptStmt _
| SEHFinallyStmt _
| SEHLeaveStmt _
| SEHTryStmt _
| DefaultStmt _
-> raise
(CFrontend_config.unimplemented "Statement translation for kind %s: %a"
(Clang_ast_proj.get_stmt_kind_string instr)
(Pp.to_string ~f:Clang_ast_j.string_of_stmt) instr)
(* Function similar to instruction function, but it takes C++ constructor initializer as (* Function similar to instruction function, but it takes C++ constructor initializer as
an input parameter. *) an input parameter. *)

@ -14,10 +14,6 @@ module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging
exception TemplatedCodeException of Clang_ast_t.stmt
exception UnsupportedStatementException of Clang_ast_t.stmt
(* Extract the element of a singleton list. If the list is not a singleton *) (* Extract the element of a singleton list. If the list is not a singleton *)
(* It stops the computation giving a warning. We use this because we *) (* It stops the computation giving a warning. We use this because we *)
(* assume in many places that a list is just a singleton. We use the *) (* assume in many places that a list is just a singleton. We use the *)
@ -653,8 +649,7 @@ let rec get_type_from_exp_stmt stmt =
| DeclRefExpr (_, _, _, info) | DeclRefExpr (_, _, _, info)
-> do_decl_ref_exp info -> do_decl_ref_exp info
| _ | _
-> L.internal_error "Failing with: %s@\n%!" (Clang_ast_j.string_of_stmt stmt) ; -> L.die InternalError "get_type_from_expr_stmt failure: %s" (Clang_ast_j.string_of_stmt stmt)
assert false
module Self = struct module Self = struct
exception SelfClassException of Typ.Name.t exception SelfClassException of Typ.Name.t
@ -793,7 +788,7 @@ let is_dispatch_function stmt_list =
try try
let arg_stmt = List.nth_exn arg_stmts block_arg_pos in let arg_stmt = List.nth_exn arg_stmts block_arg_pos in
if is_block_stmt arg_stmt then Some block_arg_pos else None if is_block_stmt arg_stmt then Some block_arg_pos else None
with Failure _ -> None ) with Invalid_argument _ -> None )
| _ | _
-> None ) -> None )
| _ -> | _ ->

@ -36,10 +36,6 @@ type trans_result =
; initd_exps: Exp.t list ; initd_exps: Exp.t list
; is_cpp_call_virtual: bool } ; is_cpp_call_virtual: bool }
exception TemplatedCodeException of Clang_ast_t.stmt
exception UnsupportedStatementException of Clang_ast_t.stmt
val empty_res_trans : trans_result val empty_res_trans : trans_result
val undefined_expression : unit -> Exp.t val undefined_expression : unit -> Exp.t

@ -118,11 +118,9 @@ let mark proc_name ann asig (b, bs) =
in in
let params' = let params' =
let fail () = let fail () =
L.internal_error L.die InternalError
"INTERNAL ERROR: annotation for procedure %s has wrong number of arguments@." "Annotation for procedure %s has wrong number of arguments.@\n Annotated signature: %a"
(Typ.Procname.to_unique_id proc_name) ; (Typ.Procname.to_unique_id proc_name) (pp proc_name) asig
L.internal_error " ANNOTATED SIGNATURE: %a@." (pp proc_name) asig ;
assert false
in in
let rec combine l1 l2 = let rec combine l1 l2 =
match (l1, l2) with match (l1, l2) with

@ -44,9 +44,7 @@ module Inference = struct
if String.is_empty s_old then 0 if String.is_empty s_old then 0
else else
try int_of_string s_old try int_of_string s_old
with Failure _ -> with Failure _ -> L.die InternalError "int_of_string %s" s_old
L.internal_error "int_of_string %s@." s_old ;
assert false
in in
string_of_int (n + 1) string_of_int (n + 1)

@ -150,8 +150,7 @@ let rec inhabit_typ tenv typ cfg env =
| Typ.Tfloat _ | Typ.Tfloat _
-> (Exp.Const (Const.Cfloat 0.0), env) -> (Exp.Const (Const.Cfloat 0.0), env)
| _ | _
-> L.internal_error "Couldn't inhabit typ: %a@." (Typ.pp Pp.text) typ ; -> L.die InternalError "Couldn't inhabit typ: %a" (Typ.pp Pp.text) typ
assert false
in in
let inhabited_exp, env' = let inhabited_exp, env' =
inhabit_internal typ {env with cur_inhabiting= TypSet.add typ env.cur_inhabiting} inhabit_internal typ {env with cur_inhabiting= TypSet.add typ env.cur_inhabiting}

Loading…
Cancel
Save