Newer
Older
(**************************************************************************)
(* *)
(* This file is part of Frama-C. *)
(* *)
(* CEA (Commissariat à l'énergie atomique et aux énergies *)
(* alternatives) *)
(* *)
(* you can redistribute it and/or modify it under the terms of the GNU *)
(* Lesser General Public License as published by the Free Software *)
(* Foundation, version 2.1. *)
(* *)
(* It is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
(* GNU Lesser General Public License for more details. *)
(* *)
(* See the GNU Lesser General Public License version 2.1 *)
(* for more details (enclosed in the file licenses/LGPLv2.1). *)
(* *)
(**************************************************************************)
open Cil_types
module Retres =
Kernel_function.Make_Table
(Datatype.Option(Cil_datatype.Varinfo))
(struct
let name = "Value.Library_functions.Retres"
let size = 9
let dependencies = [Ast.self]
end)
let () = Ast.add_monotonic_state Retres.self
let () =
State_dependency_graph.add_dependencies ~from:Retres.self [ Self.state ]
let get_retres_vi = Retres.memo
(fun kf ->
let vi = Kernel_function.get_vi kf in
let typ = Cil.getReturnType vi.vtype in
if Cil.isVoidType typ then
None
else
try
ignore (Cil.bitsSizeOf typ);
let name = Format.asprintf "\\result<%a>" Kernel_function.pretty kf in
Some (Cil.makeVarinfo false false name typ)
with Cil.SizeOfError _ ->
Self.abort ~current:true
"function %a returns a value of unknown size. Aborting"
Kernel_function.pretty kf
)
let returned_value kf =
let return_type = Cil.unrollType (Kernel_function.get_return_type kf) in
match return_type with
| TComp _ when Cil.is_fully_arithmetic return_type -> Cvalue.V.top_int
| TPtr _ | TComp _ -> Cvalue.V.inject Base.null Ival.zero
| TInt _ | TEnum _ -> Cvalue.V.top_int
| TFloat (FFloat, _) -> Cvalue.V.top_single_precision_float
| TFloat (FDouble, _)
| TFloat (FLongDouble, _) -> Cvalue.V.top_float
| TBuiltin_va_list _ ->
Self.error ~current:true ~once:true
"functions returning variadic arguments must be stubbed%t"
Cvalue.V.top_int
| TVoid _ -> Cvalue.V.top (* this value will never be used *)
| TFun _ | TNamed _ | TArray _ -> assert false
let unsupported_specifications =
[
"asprintf", "stdio.c";
"canonicalize_path_name", "stdlib.c";
"getaddrinfo", "netdb.c";
"getenv", "stdlib.c";
"getline", "stdio.c";
"getpwnam_r", "pwd.c";
"getpwuid_r", "pwd.c";
"glob", "glob.c";
"globfree", "glob.c";
"posix_memalign", "stdlib.c";
"putenv", "stdlib.c";
"realpath", "stdlib.c";
"setenv", "stdlib.c";
"strdup", "string.c";
"strerror", "string.c";
"strndup", "string.c";
]
let unsupported_specs_tbl =
let tbl = Hashtbl.create 10 in
List.iter
(fun (name, file) -> Hashtbl.replace tbl name file)
unsupported_specifications;
tbl
let warn_unsupported_spec name =
try
let header = Hashtbl.find unsupported_specs_tbl name in
Self.warning ~once:true ~current:true
~wkey:Self.wkey_libc_unsupported_spec
"@[The specification of function '%s' is currently not supported by Eva.@ \
Consider adding '%a'@ to the analyzed source files.@]"
name Filepath.Normalized.pretty
(Filepath.Normalized.concat Fc_config.framac_libc header)
with Not_found -> ()
(*
Local Variables:
compile-command: "make -C ../../../.."
End:
*)