|
|
|
(*
|
|
|
|
* Copyright (c) 2013 - 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 for function to retrieve the location (file, line, etc) of instructions *)
|
|
|
|
|
|
|
|
open CFrontend_utils
|
|
|
|
open Utils
|
|
|
|
|
|
|
|
(* The file passed as an argument to InferClang *)
|
|
|
|
let current_source_file = ref DB.source_file_empty
|
|
|
|
|
|
|
|
(* Inside the json there may be code or type definitions from other files *)
|
|
|
|
(* than the one passed as an argument. That current file in the translation is saved*)
|
|
|
|
(* in this variable. *)
|
|
|
|
let curr_file = ref DB.source_file_empty
|
|
|
|
|
|
|
|
let init_curr_source_file source_file =
|
|
|
|
current_source_file := source_file
|
|
|
|
|
|
|
|
let source_file_from_path path =
|
|
|
|
if Filename.is_relative path then
|
|
|
|
(Logging.out
|
|
|
|
"ERROR: Path %s is relative. Please pass an absolute path in the -c argument.@."
|
|
|
|
path;
|
|
|
|
exit 1);
|
|
|
|
match !Config.project_root with
|
|
|
|
| Some root ->
|
|
|
|
(try
|
|
|
|
DB.rel_source_file_from_abs_path root path
|
|
|
|
with DB.Path_not_prefix_root ->
|
|
|
|
DB.source_file_from_string path)
|
|
|
|
| None -> DB.source_file_from_string path
|
|
|
|
|
|
|
|
let choose_sloc sloc1 sloc2 prefer_first =
|
|
|
|
let sloc_bad sloc =
|
|
|
|
match sloc.Clang_ast_t.sl_file with
|
|
|
|
| Some f when not (DB.source_file_equal (source_file_from_path f) !curr_file) ->
|
|
|
|
true
|
|
|
|
| _ -> false in
|
|
|
|
if sloc_bad sloc1 then sloc2
|
|
|
|
else if prefer_first then sloc1 else sloc2
|
|
|
|
|
|
|
|
let choose_sloc_to_update_curr_file sloc1 sloc2 =
|
|
|
|
let sloc_curr_file sloc =
|
|
|
|
match sloc.Clang_ast_t.sl_file with
|
|
|
|
| Some f when DB.source_file_equal (source_file_from_path f) !current_source_file ->
|
|
|
|
true
|
|
|
|
| _ -> false in
|
|
|
|
if sloc_curr_file sloc2 then sloc2
|
|
|
|
else sloc1
|
|
|
|
|
|
|
|
let update_curr_file di =
|
|
|
|
match di.Clang_ast_t.di_source_range with (loc_start, loc_end) ->
|
|
|
|
let loc = choose_sloc_to_update_curr_file loc_start loc_end in
|
|
|
|
(match loc.Clang_ast_t.sl_file with
|
|
|
|
| Some f -> curr_file := source_file_from_path f
|
|
|
|
| None -> ())
|
|
|
|
|
|
|
|
let clang_to_sil_location clang_loc parent_line_number procdesc_opt =
|
|
|
|
let line = match clang_loc.Clang_ast_t.sl_line with
|
|
|
|
| Some l -> l
|
|
|
|
| None -> parent_line_number in
|
|
|
|
let col = match clang_loc.Clang_ast_t.sl_column with
|
|
|
|
| Some c -> c
|
|
|
|
| None -> -1 in
|
|
|
|
let file, nLOC =
|
|
|
|
match procdesc_opt with
|
|
|
|
| Some procdesc ->
|
|
|
|
let proc_loc = Cfg.Procdesc.get_loc procdesc in
|
|
|
|
if (DB.source_file_equal proc_loc.Sil.file DB.source_file_empty) then
|
|
|
|
!curr_file, !Config.nLOC
|
|
|
|
else proc_loc.Sil.file, proc_loc.Sil.nLOC
|
|
|
|
| None ->
|
|
|
|
match clang_loc.Clang_ast_t.sl_file with
|
|
|
|
| Some f ->
|
|
|
|
let file_db = source_file_from_path f in
|
|
|
|
let nloc =
|
|
|
|
if (DB.source_file_equal file_db !current_source_file) then
|
|
|
|
!Config.nLOC
|
|
|
|
else -1 in
|
|
|
|
file_db, nloc
|
|
|
|
| None -> !curr_file, !Config.nLOC in
|
|
|
|
{ Sil.line = line; Sil.col = col; Sil.file = file; Sil.nLOC = nLOC }
|
|
|
|
|
|
|
|
let should_translate_lib source_range =
|
|
|
|
if !CFrontend_config.no_translate_libs then
|
|
|
|
match source_range with (loc_start, loc_end) ->
|
|
|
|
let loc_start = choose_sloc_to_update_curr_file loc_start loc_end in
|
|
|
|
let loc = clang_to_sil_location loc_start (-1) None in
|
|
|
|
DB.source_file_equal loc.Sil.file !DB.current_source
|
|
|
|
else true
|
|
|
|
|
|
|
|
let should_translate_enum source_range =
|
|
|
|
if !CFrontend_config.testing_mode then
|
|
|
|
match source_range with (loc_start, loc_end) ->
|
|
|
|
let loc_start = choose_sloc_to_update_curr_file loc_start loc_end in
|
|
|
|
let loc = clang_to_sil_location loc_start (-1) None in
|
|
|
|
DB.source_file_equal loc.Sil.file !DB.current_source
|
|
|
|
else true
|
|
|
|
|
|
|
|
let get_sil_location_from_range source_range prefer_first =
|
|
|
|
match source_range with (sloc1, sloc2) ->
|
|
|
|
let sloc = choose_sloc sloc1 sloc2 prefer_first in
|
|
|
|
clang_to_sil_location sloc (-1) None
|
|
|
|
|
|
|
|
let get_sil_location stmt_info parent_line_number context =
|
|
|
|
match stmt_info.Clang_ast_t.si_source_range with (sloc1, sloc2) ->
|
|
|
|
let sloc = choose_sloc sloc1 sloc2 true in
|
|
|
|
clang_to_sil_location sloc parent_line_number (Some (CContext.get_procdesc context))
|
|
|
|
|
|
|
|
let get_line stmt_info line_number =
|
|
|
|
match stmt_info.Clang_ast_t.si_source_range with
|
|
|
|
| (sloc1, sloc2) ->
|
|
|
|
let sloc = choose_sloc sloc1 sloc2 true in
|
|
|
|
(match sloc.Clang_ast_t.sl_line with
|
|
|
|
| Some l -> l
|
|
|
|
| None -> line_number)
|
|
|
|
|
|
|
|
let check_source_file source_file =
|
|
|
|
let extensions_allowed = [".m"; ".mm"; ".c"; ".cc"; ".cpp"; ".h"] in
|
|
|
|
let allowed = list_exists (fun ext -> Filename.check_suffix source_file ext) extensions_allowed in
|
|
|
|
if not allowed then
|
|
|
|
(Printing.log_stats "%s"
|
|
|
|
("\nThe source file "^source_file^
|
|
|
|
" should end with "^(Utils.list_to_string (fun x -> x) extensions_allowed)^"\n\n");
|
|
|
|
assert false)
|