@ -41,68 +41,80 @@ let parse_ctl_file linters_files =
| None -> Logging . out " No linters found. \n " ) ;
| None -> Logging . out " No linters found. \n " ) ;
In_channel . close inx ) linters_files
In_channel . close inx ) linters_files
let compute_if_context _ _ =
None (* to be extended *)
let is_factory_method ( context : CLintersContext . context ) decl =
let interface_decl_opt =
( match context . current_objc_impl with
| Some ObjCImplementationDecl ( _ , _ , _ , _ , impl_decl_info ) ->
CAst_utils . get_decl_opt_with_decl_ref impl_decl_info . oidi_class_interface
| _ -> None ) in
( match interface_decl_opt with
| Some interface_decl -> CAst_utils . is_objc_factory_method interface_decl decl
| _ -> false )
let rec do_frontend_checks_stmt ( context : CLintersContext . context ) stmt =
let rec do_frontend_checks_stmt ( context : CLintersContext . context ) stmt =
let open Clang_ast_t in
let open Clang_ast_t in
let context' = CFrontend_errors . run_frontend_checkers_on_an context ( CTL . Stmt stmt ) in
let do_all_checks_on_stmts context stmt =
let do_all_checks_on_stmts stmt =
( match stmt with
( match stmt with
| DeclStmt ( _ , _ , decl_list ) ->
| DeclStmt ( _ , _ , decl_list ) ->
IList . iter ( do_frontend_checks_decl context' ) decl_list
IList . iter ( do_frontend_checks_decl context ) decl_list
| BlockExpr ( _ , _ , _ , decl ) ->
| BlockExpr ( _ , _ , _ , decl ) ->
IList . iter ( do_frontend_checks_decl context' ) [ decl ]
IList . iter ( do_frontend_checks_decl context ) [ decl ]
| _ -> () ) ;
| _ -> () ) ;
do_frontend_checks_stmt context' stmt in
do_frontend_checks_stmt context stmt in
let stmts = CAst_utils . get_stmts_from_stmt stmt in
CFrontend_errors . invoke_set_of_checkers_on_node context ( CTL . Stmt stmt ) ;
IList . iter ( do_all_checks_on_stmts ) stmts
match stmt with
| ObjCAtSynchronizedStmt ( _ , stmt_list ) ->
let stmt_context = { context with CLintersContext . in_synchronized_block = true } in
IList . iter ( do_all_checks_on_stmts stmt_context ) stmt_list
| IfStmt ( _ , [ stmt1 ; stmt2 ; cond_stmt ; inside_if_stmt ; inside_else_stmt ] ) ->
(* here we analyze the children of the if stmt with the standard context,
except for inside_if_stmt .. . * )
IList . iter ( do_all_checks_on_stmts context ) [ stmt1 ; stmt2 ; cond_stmt ; inside_else_stmt ] ;
let inside_if_stmt_context =
{ context with CLintersContext . if_context = compute_if_context context cond_stmt } in
(* ...and here we analyze the stmt inside the if with the context
extended with the condition of the if * )
do_all_checks_on_stmts inside_if_stmt_context inside_if_stmt
| _ ->
let stmts = CAst_utils . get_stmts_from_stmt stmt in
IList . iter ( do_all_checks_on_stmts context ) stmts
and do_frontend_checks_decl ( context : CLintersContext . context ) decl =
and do_frontend_checks_decl ( context : CLintersContext . context ) decl =
let open Clang_ast_t in
let open Clang_ast_t in
let context' =
CFrontend_errors . invoke_set_of_checkers_on_node context ( CTL . Decl decl ) ;
( match decl with
match decl with
| FunctionDecl ( _ , _ , _ , fdi )
| FunctionDecl ( _ , _ , _ , fdi )
| CXXMethodDecl ( _ , _ , _ , fdi , _ )
| CXXMethodDecl ( _ , _ , _ , fdi , _ )
| CXXConstructorDecl ( _ , _ , _ , fdi , _ )
| CXXConstructorDecl ( _ , _ , _ , fdi , _ )
| CXXConversionDecl ( _ , _ , _ , fdi , _ )
| CXXConversionDecl ( _ , _ , _ , fdi , _ )
| CXXDestructorDecl ( _ , _ , _ , fdi , _ ) ->
| CXXDestructorDecl ( _ , _ , _ , fdi , _ ) ->
let context' = { context with CLintersContext . current_method = Some decl } in
let context' = { context with CLintersContext . current_method = Some decl } in
( match fdi . Clang_ast_t . fdi_body with
( match fdi . Clang_ast_t . fdi_body with
| Some stmt ->
| Some stmt -> do_frontend_checks_stmt context' stmt
do_frontend_checks_stmt context' stmt
| None -> () )
| None -> () ) ;
| ObjCMethodDecl ( _ , _ , mdi ) ->
context'
let context' = { context with
| ObjCMethodDecl ( _ , _ , mdi ) ->
CLintersContext . current_method = Some decl ;
let if_decl_opt =
CLintersContext . in_objc_static_factory_method =
( match context . current_objc_impl with
is_factory_method context decl } in
| Some ObjCImplementationDecl ( _ , _ , _ , _ , impl_decl_info ) ->
( match mdi . Clang_ast_t . omdi_body with
CAst_utils . get_decl_opt_with_decl_ref impl_decl_info . oidi_class_interface
| Some stmt -> do_frontend_checks_stmt context' stmt
| _ -> None ) in
| None -> () )
let is_factory_method =
| BlockDecl ( _ , block_decl_info ) ->
( match if_decl_opt with
let context' = { context with CLintersContext . current_method = Some decl } in
| Some if_decl -> CAst_utils . is_objc_factory_method if_decl decl
( match block_decl_info . Clang_ast_t . bdi_body with
| _ -> false ) in
| Some stmt -> do_frontend_checks_stmt context' stmt
let context' = { context with
| None -> () )
CLintersContext . current_method = Some decl ;
| ObjCImplementationDecl ( _ , _ , decls , _ , _ ) ->
CLintersContext . in_objc_static_factory_method = is_factory_method } in
let context' = { context with current_objc_impl = Some decl } in
( match mdi . Clang_ast_t . omdi_body with
IList . iter ( do_frontend_checks_decl context' ) decls
| Some stmt ->
| _ -> match Clang_ast_proj . get_decl_context_tuple decl with
do_frontend_checks_stmt context' stmt
| Some ( decls , _ ) ->
| None -> () ) ;
IList . iter ( do_frontend_checks_decl context ) decls
context'
| None -> ()
| BlockDecl ( _ , block_decl_info ) ->
let context' = { context with CLintersContext . current_method = Some decl } in
( match block_decl_info . Clang_ast_t . bdi_body with
| Some stmt ->
do_frontend_checks_stmt context' stmt
| None -> () ) ;
context'
| _ -> context ) in
let context'' = CFrontend_errors . run_frontend_checkers_on_an context' ( CTL . Decl decl ) in
let context_with_orig_current_method =
{ context'' with CLintersContext . current_method = context . current_method } in
match Clang_ast_proj . get_decl_context_tuple decl with
| Some ( decls , _ ) -> IList . iter ( do_frontend_checks_decl context_with_orig_current_method ) decls
| None -> ()
let context_with_ck_set context decl_list =
let context_with_ck_set context decl_list =
let is_ck = context . CLintersContext . is_ck_translation_unit
let is_ck = context . CLintersContext . is_ck_translation_unit
@ -129,12 +141,12 @@ let do_frontend_checks trans_unit_ctx ast =
| Clang_ast_t . TranslationUnitDecl ( _ , decl_list , _ , _ ) ->
| Clang_ast_t . TranslationUnitDecl ( _ , decl_list , _ , _ ) ->
let context =
let context =
context_with_ck_set ( CLintersContext . empty trans_unit_ctx ) decl_list in
context_with_ck_set ( CLintersContext . empty trans_unit_ctx ) decl_list in
ignore ( CFrontend_errors . run_translation_unit_checker context ast ) ;
ignore ( CFrontend_errors . run_frontend_checkers_on_an context ( CTL . Decl ast ) ) ;
let is_decl_allowed decl =
let is_decl_allowed decl =
let decl_info = Clang_ast_proj . get_decl_tuple decl in
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
CLocation . should_do_frontend_check trans_unit_ctx decl_info . Clang_ast_t . di_source_range in
let allowed_decls = IList . filter is_decl_allowed decl_list in
let allowed_decls = IList . filter 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 . Decl ast ) ;
IList . iter ( do_frontend_checks_decl context ) allowed_decls ;
IList . iter ( do_frontend_checks_decl context ) allowed_decls ;
if ( LintIssues . exists_issues () ) then
if ( LintIssues . exists_issues () ) then
store_issues source_file ;
store_issues source_file ;