diff --git a/facebook-clang-plugins b/facebook-clang-plugins index 545b4f6e2..07c2aabb2 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit 545b4f6e27473523ad624e9a6305d7fa234946d4 +Subproject commit 07c2aabb21fb201ac01b261095b665a53a00a9a1 diff --git a/infer/src/clang/cAstProcessor.ml b/infer/src/clang/cAstProcessor.ml deleted file mode 100644 index 64bb0541f..000000000 --- a/infer/src/clang/cAstProcessor.ml +++ /dev/null @@ -1,351 +0,0 @@ -(* - * Copyright (c) 2015 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -(** Module to preprocess location information in the AST. - The original location information is incremental, each location is a delta - w.r.t. the previous one. This module processes the AST and makes locations explicit. *) - -open Utils - -module L = Logging -module F = Format - - -(** Get the sub-declarations of the current declaration. *) -let decl_get_sub_decls decl = - let open Clang_ast_t in - match decl with - | CXXRecordDecl (_, _, _, _, decl_list, _, _, _) - | ClassTemplateSpecializationDecl (_, _, _, _, decl_list, _, _, _) - | RecordDecl (_, _, _, _, decl_list, _, _) - | ObjCInterfaceDecl (_, _, decl_list, _, _) - | ObjCProtocolDecl (_, _, decl_list, _, _) - | ObjCCategoryDecl (_, _, decl_list, _, _) - | ObjCCategoryImplDecl (_, _, decl_list, _, _) - | ObjCImplementationDecl (_, _, decl_list, _, _) - | EnumDecl (_, _, _, _, decl_list, _, _) - | LinkageSpecDecl (_, decl_list, _) - | NamespaceDecl (_, _, decl_list, _, _) -> - decl_list - | ClassTemplateDecl (_, _, template_decl_info) - | FunctionTemplateDecl (_, _, template_decl_info) -> - template_decl_info.tdi_specializations - | _ -> - [] - - -(** Set the sub-declarations of the current declaration. *) -let decl_set_sub_decls decl decl_list' = - let open Clang_ast_t in - match decl with - | CXXRecordDecl (decl_info, name, opt_type, type_ptr, decl_list, decl_context_info, record_decl_info, cxx_record_info) -> - CXXRecordDecl (decl_info, name, opt_type, type_ptr, decl_list', decl_context_info, record_decl_info, cxx_record_info) - | ClassTemplateSpecializationDecl (decl_info, name, opt_type, type_ptr, decl_list, decl_context_info, record_decl_info, cxx_record_info) -> - ClassTemplateSpecializationDecl (decl_info, name, opt_type, type_ptr, decl_list', decl_context_info, record_decl_info, cxx_record_info) - | RecordDecl (decl_info, name, opt_type, type_ptr, decl_list, decl_context_info, record_decl_info) -> - RecordDecl (decl_info, name, opt_type, type_ptr, decl_list', decl_context_info, record_decl_info) - | ObjCInterfaceDecl (decl_info, name, decl_list, decl_context_info, obj_c_interface_decl_info) -> - ObjCInterfaceDecl (decl_info, name, decl_list', decl_context_info, obj_c_interface_decl_info) - | ObjCProtocolDecl (decl_info, name, decl_list, decl_context_info, obj_c_protocol_decl_info) -> - ObjCProtocolDecl (decl_info, name, decl_list', decl_context_info, obj_c_protocol_decl_info) - | ObjCCategoryDecl (decl_info, name, decl_list, decl_context_info, category_decl_info) -> - ObjCCategoryDecl (decl_info, name, decl_list', decl_context_info, category_decl_info) - | ObjCCategoryImplDecl (decl_info, name, decl_list, decl_context_info, category_impl_info) -> - ObjCCategoryImplDecl (decl_info, name, decl_list', decl_context_info, category_impl_info) - | ObjCImplementationDecl (decl_info, class_name, decl_list, decl_context_info, idi) -> - ObjCImplementationDecl (decl_info, class_name, decl_list', decl_context_info, idi) - | EnumDecl (decl_info, name, opt_type, type_ptr, decl_list, decl_context_info, enum_decl_info) -> - EnumDecl (decl_info, name, opt_type, type_ptr, decl_list', decl_context_info, enum_decl_info) - | LinkageSpecDecl (decl_info, decl_list, decl_context_info) -> - LinkageSpecDecl (decl_info, decl_list', decl_context_info) - | NamespaceDecl (decl_info, name, decl_list, decl_context_info, namespace_decl_info) -> - NamespaceDecl (decl_info, name, decl_list', decl_context_info, namespace_decl_info) - | ClassTemplateDecl (decl_info, name, template_decl_info) -> - let template_decl_info' = { tdi_specializations = decl_list' } in - ClassTemplateDecl (decl_info, name, template_decl_info') - | FunctionTemplateDecl (decl_info, name, template_decl_info) -> - let template_decl_info' = { tdi_specializations = decl_list' } in - FunctionTemplateDecl (decl_info, name, template_decl_info') - | _ -> - decl - - -(** Pretty print a source location. *) -let pp_source_loc fmt source_loc = - let file = match source_loc.Clang_ast_t.sl_file with - | Some file -> file - | None -> "None" in - let line = match source_loc.Clang_ast_t.sl_line with - | Some n -> string_of_int n - | None -> "None" in - let column = match source_loc.Clang_ast_t.sl_column with - | Some n -> string_of_int n - | None -> "None" in - if file = "None" && line = "None" && column = "None" - then F.fprintf fmt "_" - else F.fprintf fmt "%s:%s:%s" file line column - - -(** Pretty print a source range. *) -let pp_source_range fmt (sloc1, sloc2) = - F.fprintf fmt "<%a, %a>" pp_source_loc sloc1 pp_source_loc sloc2 - - -(** Pretty print an AST. *) -let pp_ast_decl fmt ast_decl = - let rec dump_stmt prefix stmt = - let prefix1 = prefix ^ " " in - let stmt_str = Clang_ast_proj.get_stmt_kind_string stmt in - let stmt_info, stmt_list = Clang_ast_proj.get_stmt_tuple stmt in - let decl_list = match stmt with - | Clang_ast_t.DeclStmt (_, _, decl_list) -> decl_list - | Clang_ast_t.BlockExpr (_, _, _, decl) -> [decl] - | _ -> [] in - F.fprintf fmt "%s%s %a@\n" - prefix - stmt_str - pp_source_range stmt_info.Clang_ast_t.si_source_range; - IList.iter (dump_stmt prefix1) stmt_list; - IList.iter (dump_decl prefix1) decl_list - and dump_decl prefix decl = - let prefix1 = prefix ^ " " in - let open Clang_ast_t in - match decl with - | BlockDecl (decl_info, block_decl_info) -> - F.fprintf fmt "%sBlockDecl %a@\n" - prefix - pp_source_range decl_info.di_source_range; - Option.may (dump_stmt prefix1) block_decl_info.bdi_body - | FunctionDecl (decl_info, name, tp, fdecl_info) -> - F.fprintf fmt "%sFunctionDecl %s %a@\n" - prefix - name.Clang_ast_t.ni_name - pp_source_range decl_info.di_source_range; - IList.iter (dump_decl prefix1) fdecl_info.fdi_decls_in_prototype_scope; - IList.iter (dump_decl prefix1) fdecl_info.fdi_parameters; - Option.may (dump_stmt prefix1) fdecl_info.fdi_body - | ObjCMethodDecl (decl_info, name, obj_c_method_decl_info) -> - F.fprintf fmt "%sObjCMethodDecl %s %a@\n" - prefix - name.Clang_ast_t.ni_name - pp_source_range decl_info.di_source_range; - Option.may (dump_stmt prefix1) obj_c_method_decl_info.omdi_body - | VarDecl (decl_info, name, type_ptr, var_decl_info) -> - F.fprintf fmt "%sVarDecl %a@\n" - prefix - pp_source_range decl_info.di_source_range; - Option.may (dump_stmt prefix1) var_decl_info.vdi_init_expr - | _ -> - let decl_kind_str = Clang_ast_proj.get_decl_kind_string decl in - let decl_info = Clang_ast_proj.get_decl_tuple decl in - let decl_list = decl_get_sub_decls decl in - F.fprintf fmt "%s%s %a@\n" - prefix - decl_kind_str - pp_source_range decl_info.di_source_range; - IList.iter (dump_decl prefix1) decl_list in - - let decl_str = Clang_ast_proj.get_decl_kind_string ast_decl in - match ast_decl with - | Clang_ast_t.TranslationUnitDecl (_, decl_list, _, _) -> - F.fprintf fmt "%s (%d declarations)@\n" decl_str (IList.length decl_list); - IList.iter (dump_decl "") decl_list - | _ -> - assert false - - -(** Compose incremental location information and make locations explicit. *) -module LocComposer : sig - (** Status of the composer. *) - type status - - (** Create a new composer with the initial status. *) - val create : unit -> status - - (** Compose a new source_range to the current one. *) - val compose : status -> Clang_ast_t.source_range -> Clang_ast_t.source_range - - (** Set the current file if specified in the source_range. - The composer will not descend into file included from the current one. - For locations in included files, it will return instead the last known - location of the current file. *) - val set_current_file : status -> Clang_ast_t.source_range -> unit -end = struct - type status = - { mutable curr_file: string option; - mutable curr_source_range: Clang_ast_t.source_range; - mutable in_curr_file : bool } - - let empty_sloc = { Clang_ast_t.sl_file = None; sl_line = None; sl_column = None } - - let create () = - { curr_file = None; - curr_source_range = (empty_sloc, empty_sloc); - in_curr_file = true; } - - let set_current_file st (sloc1, sloc2) = - match sloc1.Clang_ast_t.sl_file, sloc2.Clang_ast_t.sl_file with - | _, Some fname - | Some fname, None -> - st.curr_file <- Some fname; - st.in_curr_file <- true - | _ -> - () - - let sloc_is_current_file st sloc = match st.curr_file, sloc.Clang_ast_t.sl_file with - | Some curr_f, Some f -> - Some (f = curr_f) - | None, _ -> None - | _, None -> None - - let update_sloc st old_sloc new_sloc = - match sloc_is_current_file st new_sloc with - | Some true -> - st.in_curr_file <- true; - new_sloc - | Some false -> - st.in_curr_file <- false; - old_sloc - | None -> - if st.in_curr_file - then - let update x_opt y_opt = - if y_opt <> None then y_opt else x_opt in - let open Clang_ast_t in - { sl_file = update old_sloc.sl_file new_sloc.sl_file; - sl_line = update old_sloc.sl_line new_sloc.sl_line; - sl_column = update old_sloc.sl_column new_sloc.sl_column } - else - old_sloc - - let update_status st (sloc1, sloc2) = - if sloc1 = empty_sloc && sloc2 = empty_sloc - then - () - else - let _, old_sloc2 = st.curr_source_range in - let new_sloc1 = update_sloc st old_sloc2 sloc1 in - let new_sloc2 = update_sloc st new_sloc1 sloc2 in - st.curr_source_range <- (new_sloc1, new_sloc2) - - let compose st source_range = - update_status st source_range; - st.curr_source_range -end - - -let ctor_initializer_process_locs loc_composer ctor_init = - let range' = LocComposer.compose loc_composer ctor_init.Clang_ast_t.xci_source_range in - { ctor_init with Clang_ast_t.xci_source_range = range'} - -(** Apply a location composer to the locations in a statement. *) -let rec stmt_process_locs loc_composer stmt = - let update (stmt_info, stmt_list) = - let range' = LocComposer.compose loc_composer stmt_info.Clang_ast_t.si_source_range in - let stmt_info' = - { stmt_info with - Clang_ast_t.si_source_range = range' } in - let stmt_list' = IList.map (stmt_process_locs loc_composer) stmt_list in - (stmt_info', stmt_list') in - let open Clang_ast_t in - match Clang_ast_proj.update_stmt_tuple update stmt with - | DeclStmt (stmt_info, stmt_list, decl_list) -> - let decl_list' = IList.map (decl_process_locs loc_composer) decl_list in - DeclStmt (stmt_info, stmt_list, decl_list') - | BlockExpr (stmt_info, stmt_list, expr_info, block_decl) -> - let block_decl' = decl_process_locs loc_composer block_decl in - BlockExpr (stmt_info, stmt_list, expr_info, block_decl') - | OpaqueValueExpr (stmt_info, stmt_list, expr_info, opaque_value_ei) -> - let source_expr = opaque_value_ei.ovei_source_expr in - let ovei_source_expr' = Option.map (stmt_process_locs loc_composer) source_expr in - let opaque_value_ei' = { ovei_source_expr = ovei_source_expr' } in - OpaqueValueExpr (stmt_info, stmt_list, expr_info, opaque_value_ei') - | stmt' -> - stmt' - -(** Apply a location composer to the locations in a declaration. *) -and decl_process_locs loc_composer decl = - let decl' = - let update decl_info = - let range' = LocComposer.compose loc_composer decl_info.Clang_ast_t.di_source_range in - { decl_info with - Clang_ast_t.di_source_range = range' } in - let decl_list = decl_get_sub_decls decl in - let decl1 = Clang_ast_proj.update_decl_tuple update decl in - let decl_list' = IList.map (decl_process_locs loc_composer) decl_list in - decl_set_sub_decls decl1 decl_list' in - let open Clang_ast_t in - let get_updated_fun_decl (decl_info', name, tp, fdecl_info) = - let fdi_decls_in_prototype_scope' = - IList.map (decl_process_locs loc_composer) fdecl_info.fdi_decls_in_prototype_scope in - let fdi_parameters' = - IList.map (decl_process_locs loc_composer) fdecl_info.fdi_parameters in - let body' = Option.map (stmt_process_locs loc_composer) fdecl_info.fdi_body in - let fdecl_info' = - { fdecl_info with - fdi_body = body'; - fdi_parameters = fdi_parameters'; - fdi_decls_in_prototype_scope = fdi_decls_in_prototype_scope'; } in - (decl_info', name, tp, fdecl_info') in - let get_updated_method_decl (decl_info', name, tp, fdecl_info, method_info) = - let di', n', tp', fdi' = get_updated_fun_decl (decl_info', name, tp, fdecl_info) in - let ctor_init = method_info.xmdi_cxx_ctor_initializers in - let ctor_init' = IList.map (ctor_initializer_process_locs loc_composer) ctor_init in - let method_info' = { method_info with xmdi_cxx_ctor_initializers = ctor_init'} in - (di', n', tp', fdi', method_info') in - match decl' with - | BlockDecl (decl_info', block_decl_info) -> - let parameters' = IList.map (decl_process_locs loc_composer) block_decl_info.bdi_parameters in - let body' = - Option.map (stmt_process_locs loc_composer) block_decl_info.bdi_body in - let block_decl_info' = - { block_decl_info with - bdi_body = body'; - bdi_parameters = parameters'; } in - BlockDecl (decl_info', block_decl_info') - | FunctionDecl fun_info -> FunctionDecl (get_updated_fun_decl fun_info) - | CXXMethodDecl meth_info -> CXXMethodDecl (get_updated_method_decl meth_info) - | CXXConstructorDecl meth_info -> CXXConstructorDecl (get_updated_method_decl meth_info) - | ObjCMethodDecl (decl_info', name, obj_c_method_decl_info) -> - let body' = - Option.map (stmt_process_locs loc_composer) obj_c_method_decl_info.omdi_body in - let obj_c_method_decl_info' = { obj_c_method_decl_info with omdi_body = body' } in - ObjCMethodDecl (decl_info', name, obj_c_method_decl_info') - | VarDecl (decl_info, string, type_ptr, var_decl_info) -> - let vdi_init_expr' = - Option.map (stmt_process_locs loc_composer) var_decl_info.vdi_init_expr in - let var_decl_info' = - { var_decl_info with vdi_init_expr = vdi_init_expr' } in - VarDecl (decl_info, string, type_ptr, var_decl_info') - | _ -> - decl' - - -(** Process locations in the AST by making them explicit. - Each toplevel declaration determines the current file, - and once diving into the details of the declaration, location - information about other (include) files is ignored. *) -let ast_decl_process_locs loc_composer ast_decl = - - let toplevel_decl_process_locs decl = - let decl_info = Clang_ast_proj.get_decl_tuple decl in - LocComposer.set_current_file loc_composer decl_info.Clang_ast_t.di_source_range; - decl_process_locs loc_composer decl in - - match ast_decl with - | Clang_ast_t.TranslationUnitDecl (decl_info, decl_list, decl_context_info, type_list) -> - let decl_list' = IList.map toplevel_decl_process_locs decl_list in - Clang_ast_t.TranslationUnitDecl (decl_info, decl_list', decl_context_info, type_list) - | _ -> - assert false - - -let preprocess_ast_decl ast_decl = - let loc_composer = LocComposer.create () in - ast_decl_process_locs loc_composer ast_decl diff --git a/infer/src/clang/cAstProcessor.mli b/infer/src/clang/cAstProcessor.mli deleted file mode 100644 index f0719083a..000000000 --- a/infer/src/clang/cAstProcessor.mli +++ /dev/null @@ -1,18 +0,0 @@ -(* - * Copyright (c) 2015 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -(** Module to preprocess location information in the AST. - The original location information is incremental, each location is a delta - w.r.t. the previous one. This module processes the AST and makes locations explicit. *) - -(** Pretty print an AST. *) -val pp_ast_decl : Format.formatter -> Clang_ast_t.decl -> unit - -(** Preprocess the AST to make locations explicit. *) -val preprocess_ast_decl : Clang_ast_t.decl -> Clang_ast_t.decl diff --git a/infer/src/clang/cMain.ml b/infer/src/clang/cMain.ml index acb1e0f32..357f4b7f4 100644 --- a/infer/src/clang/cMain.ml +++ b/infer/src/clang/cMain.ml @@ -97,18 +97,14 @@ let do_run source_path ast_path = | Some path -> path, validate_decl_from_file path | None -> "stdin of " ^ source_path, validate_decl_from_stdin () in - let ast_decl' = CAstProcessor.preprocess_ast_decl ast_decl in - Printing.log_out "Original AST@.%a@." CAstProcessor.pp_ast_decl ast_decl; - Printing.log_out "AST with explicit locations:@.%a@." CAstProcessor.pp_ast_decl ast_decl'; - - let decl_index, _, type_index = Clang_ast_main.index_node_pointers ast_decl' in + let decl_index, _, type_index = Clang_ast_main.index_node_pointers ast_decl in CFrontend_config.pointer_decl_index := decl_index; CFrontend_config.pointer_type_index := type_index; CFrontend_config.json := ast_filename; CLocation.check_source_file source_path; let source_file = CLocation.source_file_from_path source_path in print_endline ("Start translation of AST from " ^ !CFrontend_config.json); - CFrontend.do_source_file source_file ast_decl'; + CFrontend.do_source_file source_file ast_decl; print_endline ("End translation AST file " ^ !CFrontend_config.json ^ "... OK!") with (Yojson.Json_error s) as exc -> Printing.log_err "%s\n" s; diff --git a/infer/tests/codetoanalyze/c/frontend/loops/for_only_body.c.dot b/infer/tests/codetoanalyze/c/frontend/loops/for_only_body.c.dot index b49e57561..5e3d1871c 100644 --- a/infer/tests/codetoanalyze/c/frontend/loops/for_only_body.c.dot +++ b/infer/tests/codetoanalyze/c/frontend/loops/for_only_body.c.dot @@ -7,11 +7,11 @@ digraph iCFG { 7 -> 4 ; -6 [label="6: Prune (false branch) \n PRUNE((1 == 0), false); [line 12]\n " shape="invhouse"] +6 [label="6: Prune (false branch) \n PRUNE((1 == 0), false); [line 14]\n " shape="invhouse"] 6 -> 3 ; -5 [label="5: Prune (true branch) \n PRUNE((1 != 0), true); [line 12]\n " shape="invhouse"] +5 [label="5: Prune (true branch) \n PRUNE((1 != 0), true); [line 14]\n " shape="invhouse"] 5 -> 7 ; diff --git a/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot b/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot index 378ffbcc8..3db2f9364 100644 --- a/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot +++ b/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot @@ -14,7 +14,7 @@ digraph iCFG { 14 -> 17 ; -13 [label="13: Call _fun___infer_assume \n n$10=*&name:class NSString * [line -1]\n n$11=_fun___infer_assume((n$10 != 0):class NSString *) [line -1]\n REMOVE_TEMPS(n$10,n$11); [line -1]\n " shape="box"] +13 [label="13: Call _fun___infer_assume \n n$10=*&name:class NSString * [line 31]\n n$11=_fun___infer_assume((n$10 != 0):class NSString *) [line 31]\n REMOVE_TEMPS(n$10,n$11); [line 31]\n " shape="box"] 13 -> 12 ; @@ -29,7 +29,7 @@ digraph iCFG { 10 -> 13 ; -9 [label="9: Call _fun___infer_assume \n n$5=*&a:class A * [line -1]\n n$6=_fun___infer_assume((n$5 != 0):class A *) [line -1]\n REMOVE_TEMPS(n$5,n$6); [line -1]\n " shape="box"] +9 [label="9: Call _fun___infer_assume \n n$5=*&a:class A * [line 37]\n n$6=_fun___infer_assume((n$5 != 0):class A *) [line 37]\n REMOVE_TEMPS(n$5,n$6); [line 37]\n " shape="box"] 9 -> 8 ;