diff --git a/infer/src/base/Pp.ml b/infer/src/base/Pp.ml index a5418f6b6..9f0a18ac9 100644 --- a/infer/src/base/Pp.ml +++ b/infer/src/base/Pp.ml @@ -138,6 +138,8 @@ let elapsed_time fmt () = 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 pp_argfile fmt fname = diff --git a/infer/src/base/Pp.mli b/infer/src/base/Pp.mli index 74be752b5..ea3c94e0d 100644 --- a/infer/src/base/Pp.mli +++ b/infer/src/base/Pp.mli @@ -68,6 +68,8 @@ val latex : color -> env val color_string : color -> string (** string representation of colors *) +val option : (F.formatter -> 'a -> unit) -> F.formatter -> 'a option -> unit + val string : F.formatter -> string -> unit val cli_args : F.formatter -> string list -> unit diff --git a/infer/src/clang/Capture.ml b/infer/src/clang/Capture.ml index bf3887b05..6ce955dc0 100644 --- a/infer/src/clang/Capture.ml +++ b/infer/src/clang/Capture.ml @@ -15,25 +15,13 @@ let debug_mode = Config.debug_mode || Config.frontend_stats 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 defined in Clang_ast_t. *) 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 = - catch_biniou_buffer_errors (Ag_util.Biniou.from_channel ~len:buffer_len Clang_ast_b.read_decl) - chan + Ag_util.Biniou.from_channel ~len:buffer_len Clang_ast_b.read_decl chan let register_perf_stats_report source_file = let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in diff --git a/infer/src/clang/ast_expressions.ml b/infer/src/clang/ast_expressions.ml index cca7d8f38..56c1595cc 100644 --- a/infer/src/clang/ast_expressions.ml +++ b/infer/src/clang/ast_expressions.ml @@ -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 (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 let message_call = 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 ] , 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 let open Clang_ast_t in match stmt_list with diff --git a/infer/src/clang/cFrontend_checkers_main.ml b/infer/src/clang/cFrontend_checkers_main.ml index e29e17463..5564f9108 100644 --- a/infer/src/clang/cFrontend_checkers_main.ml +++ b/infer/src/clang/cFrontend_checkers_main.ml @@ -301,36 +301,32 @@ 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) linters_files ; CTL.create_ctl_evaluation_tracker trans_unit_ctx.source_file ; - try - let parsed_linters = parse_ctl_files linters_files in - let filtered_parsed_linters = - CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file - in - CFrontend_errors.parsed_linters := filtered_parsed_linters ; - let source_file = trans_unit_ctx.CFrontend_config.source_file in - L.(debug Linters Medium) - "Start linting file %a with rules: @\n%a@\n" SourceFile.pp source_file + let parsed_linters = parse_ctl_files linters_files in + let filtered_parsed_linters = + CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file + in + CFrontend_errors.parsed_linters := filtered_parsed_linters ; + let source_file = trans_unit_ctx.CFrontend_config.source_file in + L.(debug Linters Medium) + "Start linting file %a with rules: @\n%a@\n" SourceFile.pp source_file + CFrontend_errors.pp_linters filtered_parsed_linters ; + if Config.print_active_checkers then + L.progress "Linting file %a, active linters: @\n%a@\n" SourceFile.pp source_file CFrontend_errors.pp_linters filtered_parsed_linters ; - if Config.print_active_checkers then - L.progress "Linting file %a, active linters: @\n%a@\n" SourceFile.pp source_file - CFrontend_errors.pp_linters filtered_parsed_linters ; - match ast with - | Clang_ast_t.TranslationUnitDecl (_, decl_list, _, _) - -> let context = context_with_ck_set (CLintersContext.empty trans_unit_ctx) decl_list in - let is_decl_allowed decl = - let decl_info = Clang_ast_proj.get_decl_tuple decl in - CLocation.should_do_frontend_check trans_unit_ctx decl_info.Clang_ast_t.di_source_range - in - let allowed_decls = List.filter ~f:is_decl_allowed decl_list in - (* We analyze the top level and then all the allowed declarations *) - CFrontend_errors.invoke_set_of_checkers_on_node context (Ctl_parser_types.Decl ast) ; - List.iter ~f:(do_frontend_checks_decl context) allowed_decls ; - if LintIssues.exists_issues () then store_issues 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 - | _ - -> assert false - (* NOTE: Assumes that an AST always starts with a TranslationUnitDecl *) - 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 + match ast with + | Clang_ast_t.TranslationUnitDecl (_, decl_list, _, _) + -> let context = context_with_ck_set (CLintersContext.empty trans_unit_ctx) decl_list in + let is_decl_allowed decl = + let decl_info = Clang_ast_proj.get_decl_tuple decl in + CLocation.should_do_frontend_check trans_unit_ctx decl_info.Clang_ast_t.di_source_range + in + let allowed_decls = List.filter ~f:is_decl_allowed decl_list in + (* We analyze the top level and then all the allowed declarations *) + CFrontend_errors.invoke_set_of_checkers_on_node context (Ctl_parser_types.Decl ast) ; + List.iter ~f:(do_frontend_checks_decl context) allowed_decls ; + if LintIssues.exists_issues () then store_issues 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 + | _ + -> (* NOTE: Assumes that an AST always starts with a TranslationUnitDecl *) + assert false diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index 3a1967704..51e1fadf1 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -8,9 +8,18 @@ *) open! IStd +module F = Format (** 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] let equal_clang_lang = [%compare.equal : clang_lang] diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index 6344850e1..9df41ee3f 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -11,6 +11,18 @@ open! IStd (** 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] val equal_clang_lang : clang_lang -> clang_lang -> bool diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 54a1c9333..bd2900d6b 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -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. *) 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 = - 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 ; - 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 - L.(debug Capture Verbose) - "@\n@\n>>---------- ADDING METHOD: '%s' ---------<<@\n@." (Typ.Procname.to_string procname) ; try match Cfg.find_proc_desc_from_name cfg procname with | Some procdesc @@ -48,22 +50,21 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron | None -> () with - | Not_found - -> () - | CTrans_utils.Self.SelfClassException _ - -> (* this shouldn't happen, because self or [a class] should always be arguments of - functions. This is to make sure I'm not wrong. *) - assert false - | CTrans_utils.TemplatedCodeException _ - -> L.internal_error "Fatal error: frontend doesn't support translation of templated code@\n" ; - handle_translation_failure () - | CTrans_utils.UnsupportedStatementException stmt when Config.keep_going - -> L.internal_error "Unimplemented: translation for statement %s" - (Clang_ast_proj.get_stmt_kind_string stmt) ; - handle_translation_failure () - | Assert_failure (file, line, column) when Config.keep_going - -> L.internal_error "Fatal error: exception Assert_failure(%s, %d, %d)@\n%!" file line column ; - handle_translation_failure () + (* 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 + (t21762295) to the console. *) + | CFrontend_config.Unimplemented msg + -> handle_frontend_failure ~print:false "Unimplemented feature:@\n %s@\n" msg + | CFrontend_config.IncorrectAssumption msg + -> (* FIXME(t21762295): we do not expect this to happen but it does *) + handle_frontend_failure ~print:true "Known incorrect assumption in the frontend: %s@\n" msg + | CTrans_utils.Self.SelfClassException class_name + -> (* FIXME(t21762295): we do not expect this to happen but it does *) + handle_frontend_failure ~print:true "Unexpected SelfClassException %a@\n" Typ.Name.pp + class_name + | exn when Config.keep_going + -> handle_frontend_failure ~print:true "Frontend error: %a@\nBacktrace:@\n%s" Exn.pp exn + (Exn.backtrace ()) let function_decl trans_unit_ctx tenv cfg cg func_decl block_data_opt = let captured_vars, outer_context_opt = diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index f2b21854a..5a064c9ff 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -118,8 +118,7 @@ let evaluate_place_holder context ph an = | "%name%" -> MF.monospaced_to_string (Ctl_parser_types.ast_node_name an) | _ - -> L.internal_error "ERROR: helper function %s is unknown. Stop.@\n" ph ; - assert false + -> L.die InternalError "helper function %s is unknown" ph (* given a message this function searches for a place-holder identifier, eg %id%. Then it evaluates id and replaces %id% in message @@ -156,8 +155,7 @@ let string_to_err_kind = function | "LIKE" -> Exceptions.Klike | s - -> L.internal_error "@\n[ERROR] Severity %s does not exist. Stop.@\n" s ; - assert false + -> L.die InternalError "Severity %s does not exist" s let string_to_issue_mode m = match m with @@ -166,8 +164,7 @@ let string_to_issue_mode m = | "OFF" -> CIssue.Off | s - -> L.internal_error "@\n[ERROR] Mode %s does not exist. Please specify ON/OFF@\n" s ; - assert false + -> L.die InternalError "Mode %s does not exist. Please specify ON/OFF" s let post_process_linter_definition (linter: linter) = match diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 2dd1261b9..8ec3dabd5 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -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 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 = match dec with | Clang_ast_t.CXXRecordDecl (_, _, _, _, _, _, _, cxx_rdi) -> cxx_rdi.xrdi_lambda_captures | _ - -> (* We should not get here *) assert false - -(* -let instance_to_method_call_type instance = - if instance then MCVirtual - else MCStatic -*) + -> assert false diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 58675765e..70948dce9 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -59,7 +59,6 @@ type t = | EH of ALVar.alexp list * t | ET of ALVar.alexp list * transitions option * t - let has_transition phi = match phi with | True @@ -609,7 +608,9 @@ let transition_decl_to_stmt d trs = | InitExpr, CXXConstructorDecl _ | InitExpr, CXXConversionDecl _ | 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) -> ecdi.ecdi_init_expr | _, _ diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 0987353eb..07fbed450 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -454,7 +454,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let exps = [(exp, typ)] in {empty_res_trans with exps; instrs} | Tfun _ | Tvoid | Tarray _ | TVar _ - -> assert false + -> CFrontend_config.unimplemented "fill_typ_with_zero on type %a" (Typ.pp Pp.text) typ in let res_trans = fill_typ_with_zero var_exp_typ in {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 | _ -> assert false ) - | _ - -> assert false - (* di_parent_pointer should be always set for fields/ivars *) + | _ as decl + -> (* FIXME(t21762295): we do not expect this to happen but it does *) + 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 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 @@ -844,8 +847,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s match stmt_list with | [a; i] -> (a, i) - (* Assumption: the statement list contains 2 elements, - the first is the array expr and the second the index *) + (* Assumption: the statement list contains 2 elements, the first is the array expr and the + second the index *) | _ -> assert false (* 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 params = List.tl_exn (collect_exprs result_trans_subexprs) in if Int.equal (List.length params) (List.length params_stmt) then params - else ( - L.internal_error "ERROR: stmt_list and res_trans_par.exps must have same size@\n" ; - assert false ) + else + (* FIXME(t21762295) this is reachable *) + 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 let act_params = 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 procname = Procdesc.get_proc_name context.procdesc in let sil_loc = CLocation.get_sil_location si context in - (* first for method address, second for 'this' expression *) - assert (Int.equal (List.length result_trans_callee.exps) 2) ; + (* first for method address, second for 'this' expression and other parameters *) + assert (List.length result_trans_callee.exps >= 1) ; let sil_method, _ = List.hd_exn result_trans_callee.exps in let callee_pname = - match sil_method with Exp.Const Const.Cfun pn -> pn | _ -> assert false - (* method pointer not implemented, this shouldn't happen *) + match sil_method with + | 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 - (* As we may have nodes coming from different parameters we need to *) - (* call instruction for each parameter and collect the results *) - (* afterwards. The 'instructions' function does not do that *) + (* As we may have nodes coming from different parameters we need to call instruction for each + 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 @@ -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 act_params 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 || String.equal selector CFrontend_config.new_str 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 {op_res_trans with root_nodes= root_nodes'} | _ - -> L.(debug Capture Medium) "BinaryConditionalOperator not translated@." ; - assert false + -> CFrontend_config.unimplemented "BinaryConditionalOperator not translated" (* 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) *) @@ -1810,7 +1823,11 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s (* succ_nodes will remove the temps *) {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 = let stmt = @@ -2058,7 +2075,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | Tint _ | Tfloat _ | Tptr _ -> 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 let nname = "InitListExp" in let res_trans = @@ -2185,8 +2203,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | (RecordDecl _) :: var_decls' -> (* Record declaration is done in the beginning when procdesc is defined.*) collect_all_decl trans_state var_decls' next_nodes stmt_info - | _ - -> assert false + | decl :: _ + -> 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 *) (* 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 match decl_list with | (VarDecl _) :: _ - -> (* Case for simple variable declarations*) - collect_all_decl trans_state decl_list succ_nodes stmt_info - | (CXXRecordDecl _) :: _ (*C++/C record decl treated in the same way *) | (RecordDecl _) :: _ + (* Case for simple variable declarations*) + | (CXXRecordDecl _) :: _ + (*C++/C record decl treated in the same way *) + | (RecordDecl _) :: _ -> (* Case for struct *) collect_all_decl trans_state decl_list succ_nodes stmt_info - | _ - -> L.(debug Capture Medium) - "WARNING: In DeclStmt found an unknown declaration type. RETURNING empty list of declaration. NEED TO BE FIXED" ; - empty_res_trans + | (TypedefDecl _) :: _ | (UsingDirectiveDecl _) :: _ + -> empty_res_trans + | decl :: _ + -> CFrontend_config.unimplemented "In DeclStmt found an unknown declaration type %s" + (Clang_ast_j.string_of_decl decl) + | [] + -> assert false in {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.*) and pseudoObjectExpr_trans trans_state stmt_list = L.(debug Capture Verbose) - " priority node free = '%s'@\n@." + " priority node free = '%s'@\n@\n" (string_of_bool (PriorityNode.is_priority_free trans_state)) ; let rec do_semantic_elements el = let open Clang_ast_t in @@ -2906,9 +2930,15 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | NullStmt _, FallThroughAttr _ -> 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 = 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_trans trans_state stmt_info switch_stmt_list | CaseStmt _ - -> L.(debug Capture Verbose) - "FATAL: Passing from CaseStmt outside of SwitchStmt, terminating.@\n" ; - assert false + -> (* where do we even get case stmts outside of the switch stmt? (t21762295) *) + CFrontend_config.incorrect_assumption "Case statement outside of switch statement: %a" + (Pp.to_string ~f:Clang_ast_j.string_of_stmt) instr | StmtExpr (_, stmt_list, _) -> stmtExpr_trans trans_state stmt_list | 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 _ | SubstNonTypeTemplateParmPackExpr _ | CXXDependentScopeMemberExpr _ - -> raise (CTrans_utils.TemplatedCodeException instr) - | s - -> raise (CTrans_utils.UnsupportedStatementException s) + -> raise + (CFrontend_config.unimplemented "Translation of templated code is unsupported: %a" + (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 an input parameter. *) diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index 78f8531da..64c9c1c00 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -14,10 +14,6 @@ module Hashtbl = Caml.Hashtbl 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 *) (* 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 *) @@ -653,8 +649,7 @@ let rec get_type_from_exp_stmt stmt = | DeclRefExpr (_, _, _, info) -> do_decl_ref_exp info | _ - -> L.internal_error "Failing with: %s@\n%!" (Clang_ast_j.string_of_stmt stmt) ; - assert false + -> L.die InternalError "get_type_from_expr_stmt failure: %s" (Clang_ast_j.string_of_stmt stmt) module Self = struct exception SelfClassException of Typ.Name.t @@ -793,7 +788,7 @@ let is_dispatch_function stmt_list = try 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 - with Failure _ -> None ) + with Invalid_argument _ -> None ) | _ -> None ) | _ -> diff --git a/infer/src/clang/cTrans_utils.mli b/infer/src/clang/cTrans_utils.mli index 6edf6fdec..71fd1d296 100644 --- a/infer/src/clang/cTrans_utils.mli +++ b/infer/src/clang/cTrans_utils.mli @@ -36,10 +36,6 @@ type trans_result = ; initd_exps: Exp.t list ; 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 undefined_expression : unit -> Exp.t diff --git a/infer/src/eradicate/AnnotatedSignature.ml b/infer/src/eradicate/AnnotatedSignature.ml index 18e7df1cd..e96a0d8b6 100644 --- a/infer/src/eradicate/AnnotatedSignature.ml +++ b/infer/src/eradicate/AnnotatedSignature.ml @@ -118,11 +118,9 @@ let mark proc_name ann asig (b, bs) = in let params' = let fail () = - L.internal_error - "INTERNAL ERROR: annotation for procedure %s has wrong number of arguments@." - (Typ.Procname.to_unique_id proc_name) ; - L.internal_error " ANNOTATED SIGNATURE: %a@." (pp proc_name) asig ; - assert false + L.die InternalError + "Annotation for procedure %s has wrong number of arguments.@\n Annotated signature: %a" + (Typ.Procname.to_unique_id proc_name) (pp proc_name) asig in let rec combine l1 l2 = match (l1, l2) with diff --git a/infer/src/eradicate/models.ml b/infer/src/eradicate/models.ml index 3946e6b32..ad4bd2056 100644 --- a/infer/src/eradicate/models.ml +++ b/infer/src/eradicate/models.ml @@ -44,9 +44,7 @@ module Inference = struct if String.is_empty s_old then 0 else try int_of_string s_old - with Failure _ -> - L.internal_error "int_of_string %s@." s_old ; - assert false + with Failure _ -> L.die InternalError "int_of_string %s" s_old in string_of_int (n + 1) diff --git a/infer/src/harness/inhabit.ml b/infer/src/harness/inhabit.ml index 10b7726f3..9e32de966 100644 --- a/infer/src/harness/inhabit.ml +++ b/infer/src/harness/inhabit.ml @@ -150,8 +150,7 @@ let rec inhabit_typ tenv typ cfg env = | Typ.Tfloat _ -> (Exp.Const (Const.Cfloat 0.0), env) | _ - -> L.internal_error "Couldn't inhabit typ: %a@." (Typ.pp Pp.text) typ ; - assert false + -> L.die InternalError "Couldn't inhabit typ: %a" (Typ.pp Pp.text) typ in let inhabited_exp, env' = inhabit_internal typ {env with cur_inhabiting= TypSet.add typ env.cur_inhabiting}