[clang] Remove support for logging lint issues in procdescs

Reviewed By: jberdine

Differential Revision: D3894307

fbshipit-source-id: 99208f5
master
Dulma Churchill 8 years ago committed by Facebook Github Bot 9
parent 8554c1e342
commit a2ee69975a

@ -1382,16 +1382,18 @@ and checkers = !checkers
(** should the checkers be run? *)
and checkers_enabled = not (!eradicate || !crashcontext || !quandary)
(* TODO (t12740727): Remove this variable once the transition to linters mode is finished *)
and clang_frontend_action =
and clang_frontend_do_capture, clang_frontend_do_lint =
match !clang_frontend_action with
| Some clang_frontend_action ->
clang_frontend_action
| Some `Lint -> false, true (* no capture, lint *)
| Some `Capture -> true, false (* capture, no lint *)
| Some `Lint_and_capture -> true, true (* capture, lint *)
| None ->
match !analyzer with
| Some Linters -> `Lint
| Some Infer -> `Capture
| _ -> `Lint_and_capture
| Some Linters -> false, true (* no capture, lint *)
| Some Infer -> true, false (* capture, no lint *)
| _ -> true, true (* capture, lint *)
and clang_include_to_override = !clang_include_to_override
and clang_lang = !clang_lang
and cluster_cmdline = !cluster
@ -1490,12 +1492,6 @@ and xcode_developer_dir = !xcode_developer_dir
and xml_specs = !xml_specs
and zip_libraries = !zip_libraries
let clang_frontend_do_capture, clang_frontend_do_lint =
match clang_frontend_action with
| `Lint -> false, true
| `Capture -> true, false
| `Lint_and_capture -> true, true
let clang_frontend_action_string =
String.concat " and "
((if clang_frontend_do_capture then ["translating"] else [])

@ -167,7 +167,6 @@ val calls_csv : outfile option
val check_duplicate_symbols : bool
val checkers : bool
val checkers_enabled : bool
val clang_frontend_action : [`Lint | `Capture | `Lint_and_capture ]
val clang_frontend_action_string : string
val clang_frontend_do_capture : bool
val clang_frontend_do_lint : bool

@ -27,26 +27,13 @@ let compute_icfg source tenv ast =
Printing.log_out "\n Start creating icfg\n";
let cg = Cg.create (Some source) in
let cfg = Cfg.Node.create_cfg () in
if Config.clang_frontend_do_capture then
IList.iter (CFrontend_declImpl.translate_one_declaration tenv cg cfg `DeclTraversal)
decl_list;
IList.iter (CFrontend_declImpl.translate_one_declaration tenv cg cfg `DeclTraversal)
decl_list;
Printing.log_out "\n Finished creating icfg\n";
(cg, cfg)
| _ -> assert false (* NOTE: Assumes that an AST alsways starts with a TranslationUnitDecl *)
let register_perf_stats_report source_file =
let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in
let abbrev_source_file = DB.source_file_encoding source_file in
let stats_file = Config.perf_stats_prefix ^ "_" ^ abbrev_source_file ^ ".json" in
DB.create_dir Config.results_dir ;
DB.create_dir stats_dir ;
PerfStats.register_report_at_exit (Filename.concat stats_dir stats_file)
let init_global_state source_file =
register_perf_stats_report source_file ;
Config.curr_language := Config.Clang;
CFrontend_config.current_source := source_file;
DB.Results_dir.init source_file;
let init_global_state_capture () =
Ident.NameGenerator.reset ();
CFrontend_config.global_translation_unit_decls := [];
CFrontend_utils.General_utils.reset_block_counter ()
@ -54,16 +41,13 @@ let init_global_state source_file =
let do_source_file source_file ast =
let tenv = Tenv.create () in
CTypes_decl.add_predefined_types tenv;
init_global_state source_file;
init_global_state_capture ();
Config.nLOC := FileLOC.file_get_loc (DB.source_file_to_string source_file);
Printing.log_out "\n Start building call/cfg graph for '%s'....\n"
(DB.source_file_to_string source_file);
let call_graph, cfg = compute_icfg source_file tenv ast in
Printing.log_out "\n End building call/cfg graph for '%s'.\n"
(DB.source_file_to_string source_file);
(* TODO (t12740727): Move this call to cMain once the transition to linters mode is finished *)
if Config.clang_frontend_do_lint then
CFrontend_checkers_main.do_frontend_checks cfg call_graph source_file ast;
(* This part below is a boilerplate in every frontends. *)
(* This could be moved in the cfg_infer module *)
let source_dir = DB.source_dir_from_source_file source_file in

@ -10,21 +10,21 @@
open! Utils
open CFrontend_utils
let rec do_frontend_checks_stmt (context:CLintersContext.context) cfg cg stmt =
let rec do_frontend_checks_stmt (context:CLintersContext.context) stmt =
let open Clang_ast_t in
let context' = CFrontend_errors.run_frontend_checkers_on_stmt context cfg cg stmt in
let context' = CFrontend_errors.run_frontend_checkers_on_stmt context stmt in
let do_all_checks_on_stmts stmt =
(match stmt with
| DeclStmt (_, _, decl_list) ->
IList.iter (do_frontend_checks_decl context' cfg cg) decl_list
IList.iter (do_frontend_checks_decl context') decl_list
| BlockExpr (_, _, _, decl) ->
IList.iter (do_frontend_checks_decl context' cfg cg) [decl]
IList.iter (do_frontend_checks_decl context') [decl]
| _ -> ());
do_frontend_checks_stmt context' cfg cg stmt in
do_frontend_checks_stmt context' stmt in
let stmts = Ast_utils.get_stmts_from_stmt stmt in
IList.iter (do_all_checks_on_stmts) stmts
and do_frontend_checks_decl context cfg cg decl =
and do_frontend_checks_decl context decl =
let open Clang_ast_t in
let info = Clang_ast_proj.get_decl_tuple decl in
CLocation.update_curr_file info;
@ -37,24 +37,24 @@ and do_frontend_checks_decl context cfg cg decl =
(match fdi.Clang_ast_t.fdi_body with
| Some stmt ->
let context = {context with CLintersContext.current_method = Some decl } in
do_frontend_checks_stmt context cfg cg stmt
do_frontend_checks_stmt context stmt
| None -> ())
| ObjCMethodDecl (_, _, mdi) ->
(match mdi.Clang_ast_t.omdi_body with
| Some stmt ->
let context = {context with CLintersContext.current_method = Some decl } in
do_frontend_checks_stmt context cfg cg stmt
do_frontend_checks_stmt context stmt
| None -> ())
| BlockDecl (_, block_decl_info) ->
(match block_decl_info.Clang_ast_t.bdi_body with
| Some stmt ->
let context = {context with CLintersContext.current_method = Some decl } in
do_frontend_checks_stmt context cfg cg stmt
do_frontend_checks_stmt context stmt
| None -> ())
| _ -> ());
let context' = CFrontend_errors.run_frontend_checkers_on_decl context cfg cg decl in
let context' = CFrontend_errors.run_frontend_checkers_on_decl context decl in
match Clang_ast_proj.get_decl_context_tuple decl with
| Some (decls, _) -> IList.iter (do_frontend_checks_decl context' cfg cg) decls
| Some (decls, _) -> IList.iter (do_frontend_checks_decl context') decls
| None -> ()
let context_with_ck_set context decl_list =
@ -73,7 +73,7 @@ let store_issues source_file =
DB.filename_from_string (Filename.concat lint_issues_dir (abbrev_source_file ^ ".issue")) in
LintIssues.store_issues lint_issues_file !LintIssues.errLogMap
let do_frontend_checks cfg cg source_file ast =
let do_frontend_checks source_file ast =
Printing.log_stats "Start linting file %s\n" (DB.source_file_to_string source_file);
match ast with
| Clang_ast_t.TranslationUnitDecl(_, decl_list, _, _) ->
@ -82,9 +82,8 @@ let do_frontend_checks cfg cg source_file ast =
let decl_info = Clang_ast_proj.get_decl_tuple decl in
CLocation.should_do_frontend_check decl_info.Clang_ast_t.di_source_range in
let allowed_decls = IList.filter is_decl_allowed decl_list in
IList.iter (do_frontend_checks_decl context cfg cg) allowed_decls;
(* TODO (t12740727): Remove condition once the transition to linters mode is finished *)
if Config.clang_frontend_action = `Lint && (LintIssues.exists_issues ()) then
IList.iter (do_frontend_checks_decl context) allowed_decls;
if (LintIssues.exists_issues ()) then
store_issues source_file;
Printing.log_stats "End linting file %s\n" (DB.source_file_to_string source_file)
| _ -> assert false (* NOTE: Assumes that an AST alsways starts with a TranslationUnitDecl *)

@ -7,4 +7,4 @@
* of patent rights can be found in the PATENTS file in the same directory.
*)
val do_frontend_checks : Cfg.cfg -> Cg.t -> DB.source_file -> Clang_ast_t.decl -> unit
val do_frontend_checks : DB.source_file -> Clang_ast_t.decl -> unit

@ -76,21 +76,17 @@ let while_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning
let checker_for_while_stmt stmt_info cond checker context =
checker context stmt_info cond
let get_err_log cfg cg method_decl_opt loc =
let get_err_log method_decl_opt loc =
let procname = match method_decl_opt with
| Some method_decl -> General_utils.procname_of_decl method_decl
| None -> General_utils.get_procname_for_frontend_checks loc in
if Config.clang_frontend_action = `Lint then
LintIssues.get_err_log procname
else (* TODO (t12740727): Remove this branch once the transition to linters mode is finished *)
let pdesc = CMethod_trans.get_method_for_frontend_checks cfg cg loc in
Cfg.Procdesc.get_err_log pdesc
LintIssues.get_err_log procname
(* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *)
let log_frontend_issue cfg cg method_decl_opt key issue_desc =
let log_frontend_issue method_decl_opt key issue_desc =
let issue = issue_desc.CIssue.issue in
let loc = issue_desc.CIssue.loc in
let errlog = get_err_log cfg cg method_decl_opt loc in
let errlog = get_err_log method_decl_opt loc in
let err_desc = Errdesc.explain_frontend_warning issue_desc.CIssue.description
issue_desc.CIssue.suggestion loc in
let name = CIssue.to_string issue in
@ -111,14 +107,14 @@ let log_frontend_issue cfg cg method_decl_opt key issue_desc =
1. f a particular way to apply a checker, it's a partial function
2. context
3. the list of checkers to be applied *)
let invoke_set_of_checkers f context cfg cg key checkers =
let invoke_set_of_checkers f context key checkers =
IList.iter (fun checker ->
match f checker context with
| Some issue_desc ->
log_frontend_issue cfg cg context.CLintersContext.current_method key issue_desc
log_frontend_issue context.CLintersContext.current_method key issue_desc
| None -> ()) checkers
let run_frontend_checkers_on_stmt context cfg cg instr =
let run_frontend_checkers_on_stmt context instr =
let open Clang_ast_t in
match instr with
| ObjCIvarRefExpr (stmt_info, _, _, obj_c_ivar_ref_expr_info) ->
@ -126,40 +122,40 @@ let run_frontend_checkers_on_stmt context cfg cg instr =
let call_checker_for_ivar = checkers_for_ivar stmt_info dr_ref in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers
call_checker_for_ivar context cfg cg key ivar_access_checker_list;
call_checker_for_ivar context key ivar_access_checker_list;
context
| BlockExpr (stmt_info, _ , _, Clang_ast_t.BlockDecl (_, block_decl_info)) ->
let captured_block_vars = block_decl_info.Clang_ast_t.bdi_captured_variables in
let call_captured_vars_checker = checkers_for_capture_vars stmt_info captured_block_vars in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers call_captured_vars_checker context cfg cg key
invoke_set_of_checkers call_captured_vars_checker context key
captured_vars_checker_list;
context
| IfStmt (stmt_info, _ :: _ :: cond :: _) ->
let call_checker = checker_for_if_stmt stmt_info [cond] in
let key = Ast_utils.generate_key_stmt cond in
invoke_set_of_checkers call_checker context cfg cg key if_stmt_checker_list;
invoke_set_of_checkers call_checker context key if_stmt_checker_list;
context
| ConditionalOperator (stmt_info, first_stmt :: _, _) ->
let call_checker = checker_for_conditional_op stmt_info [first_stmt] in
let key = Ast_utils.generate_key_stmt first_stmt in
invoke_set_of_checkers call_checker context cfg cg key conditional_op_checker_list;
invoke_set_of_checkers call_checker context key conditional_op_checker_list;
context
| ForStmt (stmt_info, [_; _; cond; _; _]) ->
let call_checker = checker_for_for_stmt stmt_info [cond] in
let key = Ast_utils.generate_key_stmt cond in
invoke_set_of_checkers call_checker context cfg cg key for_stmt_checker_list;
invoke_set_of_checkers call_checker context key for_stmt_checker_list;
context
| WhileStmt (stmt_info, [_; cond; _]) ->
let call_checker = checker_for_while_stmt stmt_info [cond] in
let key = Ast_utils.generate_key_stmt cond in
invoke_set_of_checkers call_checker context cfg cg key while_stmt_checker_list;
invoke_set_of_checkers call_checker context key while_stmt_checker_list;
context
| ObjCAtSynchronizedStmt _ ->
{ context with CLintersContext.in_synchronized_block = true }
| _ -> context
let run_frontend_checkers_on_decl context cfg cg dec =
let run_frontend_checkers_on_decl context dec =
let open Clang_ast_t in
match dec with
| ObjCImplementationDecl (decl_info, _, decl_list, _, _)
@ -169,16 +165,16 @@ let run_frontend_checkers_on_decl context cfg cg dec =
| _ -> None in
let call_ns_checker = checkers_for_ns decl_info idi decl_list in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_ns_checker context cfg cg key ns_notification_checker_list;
invoke_set_of_checkers call_ns_checker context key ns_notification_checker_list;
context
| VarDecl _ ->
let call_var_checker = checker_for_var dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_var_checker context cfg cg key var_checker_list;
invoke_set_of_checkers call_var_checker context key var_checker_list;
context
| ObjCPropertyDecl (decl_info, pname_info, pdi) ->
let call_property_checker = checkers_for_property decl_info pname_info pdi in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_property_checker context cfg cg key property_checkers_list;
invoke_set_of_checkers call_property_checker context key property_checkers_list;
context
| _ -> context

@ -14,9 +14,8 @@ open! Utils
(* Run frontend checkers on a statement *)
val run_frontend_checkers_on_stmt :
CLintersContext.context ->
Cfg.cfg -> Cg.t -> Clang_ast_t.stmt -> CLintersContext.context
CLintersContext.context -> Clang_ast_t.stmt -> CLintersContext.context
(* Run frontend checkers on a declaration *)
val run_frontend_checkers_on_decl : CLintersContext.context -> Cfg.cfg -> Cg.t ->
Clang_ast_t.decl -> CLintersContext.context
val run_frontend_checkers_on_decl : CLintersContext.context -> Clang_ast_t.decl ->
CLintersContext.context

@ -33,6 +33,19 @@ let validate_decl_from_stdin () =
Printing.log_stats "WARNING: biniou buffer too short, skipping the file\n";
assert false
let register_perf_stats_report source_file =
let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in
let abbrev_source_file = DB.source_file_encoding source_file in
let stats_file = Config.perf_stats_prefix ^ "_" ^ abbrev_source_file ^ ".json" in
DB.create_dir Config.results_dir ;
DB.create_dir stats_dir ;
PerfStats.register_report_at_exit (Filename.concat stats_dir stats_file)
let init_global_state_for_capture_and_linters source_file =
register_perf_stats_report source_file;
Config.curr_language := Config.Clang;
CFrontend_config.current_source := source_file;
DB.Results_dir.init source_file
let do_run source_path ast_path =
let init_time = Unix.gettimeofday () in
@ -59,7 +72,11 @@ let do_run source_path ast_path =
Printing.log_stats "Clang frontend action is %s\n" Config.clang_frontend_action_string;
Printf.printf "Start %s of AST from %s\n" Config.clang_frontend_action_string
!CFrontend_config.json;
CFrontend.do_source_file source_file ast_decl;
init_global_state_for_capture_and_linters source_file;
if Config.clang_frontend_do_lint then
CFrontend_checkers_main.do_frontend_checks source_file ast_decl;
if Config.clang_frontend_do_capture then
CFrontend.do_source_file source_file ast_decl;
Printf.printf "End translation AST file %s... OK!\n" !CFrontend_config.json;
print_elapsed ();
with

@ -466,24 +466,6 @@ let create_procdesc_with_pointer context pointer class_name_opt name =
create_external_procdesc context.cfg callee_name false None;
callee_name
let get_method_for_frontend_checks cfg cg loc =
let proc_name = General_utils.get_procname_for_frontend_checks loc in
match Cfg.Procdesc.find_from_name cfg proc_name with
| Some pdesc -> pdesc
| None ->
let attrs = { (ProcAttributes.default proc_name Config.Clang) with
is_defined = true;
loc = loc;
} in
let pdesc = Cfg.Procdesc.create cfg attrs in
let start_node = Cfg.Node.create cfg loc (Cfg.Node.Start_node pdesc) [] pdesc in
let exit_node = Cfg.Node.create cfg loc (Cfg.Node.Exit_node pdesc) [] pdesc in
Cfg.Procdesc.set_start_node pdesc start_node;
Cfg.Procdesc.set_exit_node pdesc exit_node;
Cfg.Node.set_succs_exn cfg start_node [exit_node] [];
Cg.add_defined_node cg proc_name;
pdesc
let add_default_method_for_class class_name decl_info =
let loc = CLocation.get_sil_location_from_range decl_info.Clang_ast_t.di_source_range true in
let proc_name = Procname.get_default_objc_class_method class_name in

@ -49,8 +49,6 @@ val get_method_name_from_clang : Tenv.t -> CMethod_signature.method_signature op
val create_procdesc_with_pointer : CContext.t -> Clang_ast_t.pointer -> string option ->
string -> Procname.t
val get_method_for_frontend_checks : Cfg.cfg -> Cg.t -> Location.t -> Cfg.Procdesc.t
val add_default_method_for_class : string -> Clang_ast_t.decl_info -> unit
val get_procname_from_cpp_lambda : CContext.t -> Clang_ast_t.decl -> Procname.t

@ -498,7 +498,7 @@ class BuildIntegrationTest(unittest.TestCase):
os.path.join(CODETOANALYZE_DIR, 'componentkit'),
[{'compile': ['clang', '-x', 'objective-c++', '-std=c++11', '-c',
'TestIgnoreImports.mm'],
'infer_args': ['--cxx', '--no-filtering']}])
'infer_args': ['--cxx', '--no-filtering', '-a', 'linters']}])
def test_fail_on_issue(self):
test('fail', '--fail-on-issue flag',

@ -2,6 +2,6 @@
{
"bug_type": "MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE",
"file": "TestIgnoreImports.mm",
"procedure": "frontend_checks_8553f84118792da22c2edad39b882724"
"procedure": "SomeClass_new"
}
]

@ -1,12 +1,5 @@
/* @generated */
digraph iCFG {
37 [label="37: Exit frontend_checks_f58a0b6e21d3528ef40ccf2efe3d35a4 \n " color=yellow style=filled]
36 [label="36: Start frontend_checks_f58a0b6e21d3528ef40ccf2efe3d35a4\nFormals: \nLocals: \n " color=yellow style=filled]
36 -> 37 ;
35 [label="35: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class NSAutoreleasePool ):unsigned long ) [line 60]\n n$5=_fun_NSObject_init(n$4:class NSAutoreleasePool *) virtual [line 60]\n *&pool:class NSAutoreleasePool *=n$5 [line 60]\n " shape="box"]

@ -1,12 +1,5 @@
/* @generated */
digraph iCFG {
21 [label="21: Exit frontend_checks_5b931347d68cd9eea4643dd614e081ac \n " color=yellow style=filled]
20 [label="20: Start frontend_checks_5b931347d68cd9eea4643dd614e081ac\nFormals: \nLocals: \n " color=yellow style=filled]
20 -> 21 ;
19 [label="19: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class PropertyA ):unsigned long ) [line 43]\n n$4=_fun_PropertyA_init(n$3:class PropertyA *) virtual [line 43]\n *&a:class PropertyA *=n$4 [line 43]\n " shape="box"]

Loading…
Cancel
Save