[cleanup] move annotated_signature into its own module inside eradicate

Reviewed By: cristianoc

Differential Revision: D4473328

fbshipit-source-id: dc51f87
master
Sam Blackshear 8 years ago committed by Facebook Github Bot
parent 93f33d07b8
commit 5c2fcd02bd

@ -1285,7 +1285,7 @@ let check_dereference_error tenv pdesc (prop : Prop.normal Prop.t) lexp loc =
when Exp.equal exp deref_exp -> when Exp.equal exp deref_exp ->
let is_weak_captured_var = is_weak_captured_var pdesc pvar in let is_weak_captured_var = is_weak_captured_var pdesc pvar in
let is_nullable = let is_nullable =
if Annotations.param_is_nullable pvar ann_sig || is_weak_captured_var if AnnotatedSignature.param_is_nullable pvar ann_sig || is_weak_captured_var
then then
begin begin
nullable_obj_str := Some (Pvar.to_string pvar); nullable_obj_str := Some (Pvar.to_string pvar);

@ -62,12 +62,6 @@ let verify_annotation = "com.facebook.infer.annotation.Verify"
let visibleForTesting = "VisibleForTesting" let visibleForTesting = "VisibleForTesting"
let volatile = "volatile" let volatile = "volatile"
(** Method signature with annotations. *)
type annotated_signature = {
ret : Annot.Item.t * Typ.t; (** Annotated return type. *)
params: (Mangled.t * Annot.Item.t * Typ.t) list (** Annotated parameters. *)
} [@@deriving compare]
let ia_has_annotation_with (ia: Annot.Item.t) (predicate: Annot.t -> bool): bool = let ia_has_annotation_with (ia: Annot.Item.t) (predicate: Annot.t -> bool): bool =
List.exists ~f:(fun (a, _) -> predicate a) ia List.exists ~f:(fun (a, _) -> predicate a) ia
@ -252,142 +246,3 @@ let ia_is_ui_thread ia =
let ia_is_thread_confined ia = let ia_is_thread_confined ia =
ia_ends_with ia thread_confined ia_ends_with ia thread_confined
type annotation =
| Nullable
| Present
[@@deriving compare]
let ia_is ann ia = match ann with
| Nullable -> ia_is_nullable ia
| Present -> ia_is_present ia
(** Get a method signature with annotations from a proc_attributes. *)
let get_annotated_signature proc_attributes : annotated_signature =
let method_annotation = proc_attributes.ProcAttributes.method_annotation in
let formals = proc_attributes.ProcAttributes.formals in
let ret_type = proc_attributes.ProcAttributes.ret_type in
let (ia, ial0) = method_annotation in
let natl =
let rec extract ial parl = match ial, parl with
| ia :: ial', (name, typ) :: parl' ->
(name, ia, typ) :: extract ial' parl'
| [], (name, typ) :: parl' ->
(name, Annot.Item.empty, typ) :: extract [] parl'
| [], [] ->
[]
| _ :: _, [] ->
assert false in
IList.rev (extract (IList.rev ial0) (IList.rev formals)) in
let annotated_signature = { ret = (ia, ret_type); params = natl } in
annotated_signature
(** Check if the annotated signature is for a wrapper of an anonymous inner class method.
These wrappers have the same name as the original method, every type is Object, and the parameters
are called x0, x1, x2. *)
let annotated_signature_is_anonymous_inner_class_wrapper ann_sig proc_name =
let check_ret (ia, t) =
Annot.Item.is_empty ia && PatternMatch.type_is_object t in
let x_param_found = ref false in
let name_is_x_number name =
let name_str = Mangled.to_string name in
let len = String.length name_str in
len >= 2 &&
String.equal (String.sub name_str ~pos:0 ~len:1) "x" &&
let s = String.sub name_str ~pos:1 ~len:(len - 1) in
let is_int =
try
ignore (int_of_string s);
x_param_found := true;
true
with Failure _ -> false in
is_int in
let check_param (name, ia, t) =
if String.equal (Mangled.to_string name) "this" then true
else
name_is_x_number name &&
Annot.Item.is_empty ia &&
PatternMatch.type_is_object t in
Procname.java_is_anonymous_inner_class proc_name
&& check_ret ann_sig.ret
&& IList.for_all check_param ann_sig.params
&& !x_param_found
(** Check if the given parameter has a Nullable annotation in the given signature *)
let param_is_nullable pvar ann_sig =
List.exists
~f:(fun (param, annot, _) ->
Mangled.equal param (Pvar.get_name pvar) && ia_is_nullable annot)
ann_sig.params
(** Pretty print a method signature with annotations. *)
let pp_annotated_signature proc_name fmt annotated_signature =
let pp_ia fmt ia = if ia <> [] then F.fprintf fmt "%a " Annot.Item.pp ia in
let pp_annotated_param fmt (p, ia, t) =
F.fprintf fmt " %a%a %a" pp_ia ia (Typ.pp_full Pp.text) t Mangled.pp p in
let ia, ret_type = annotated_signature.ret in
F.fprintf fmt "%a%a %s (%a )"
pp_ia ia
(Typ.pp_full Pp.text) ret_type
(Procname.to_simplified_string proc_name)
(Pp.comma_seq pp_annotated_param) annotated_signature.params
let mk_ann_str s = { Annot.class_name = s; parameters = [] }
let mk_ann = function
| Nullable -> mk_ann_str nullable
| Present -> mk_ann_str present
let mk_ia ann ia =
if ia_is ann ia then ia
else (mk_ann ann, true) :: ia
let mark_ia ann ia x =
if x then mk_ia ann ia else ia
let mk_ia_strict ia =
if ia_get_strict ia <> None then ia
else (mk_ann_str strict, true) :: ia
let mark_ia_strict ia x =
if x then mk_ia_strict ia else ia
(** Mark the annotated signature with the given annotation map. *)
let annotated_signature_mark proc_name ann asig (b, bs) =
let ia, t = asig.ret in
let ret' = mark_ia ann ia b, t in
let mark_param (s, ia, t) x =
let ia' = if x then mk_ia ann ia else ia in
(s, ia', t) in
let params' =
let fail () =
L.stdout
"INTERNAL ERROR: annotation for procedure %s has wrong number of arguments@."
(Procname.to_unique_id proc_name);
L.stdout " ANNOTATED SIGNATURE: %a@." (pp_annotated_signature proc_name) asig;
assert false in
let rec combine l1 l2 = match l1, l2 with
| (p, ia, t):: l1', l2' when String.equal (Mangled.to_string p) "this" ->
(p, ia, t) :: combine l1' l2'
| (s, ia, t):: l1', x:: l2' ->
mark_param (s, ia, t) x :: combine l1' l2'
| [], _:: _ -> fail ()
| _:: _, [] -> fail ()
| [], [] -> [] in
combine asig.params bs in
{ ret = ret'; params = params'}
(** Mark the return of the annotated signature with the given annotation. *)
let annotated_signature_mark_return ann asig =
let ia, t = asig.ret in
let ret' = mark_ia ann ia true, t in
{ asig with ret = ret'}
(** Mark the return of the annotated signature @Strict. *)
let annotated_signature_mark_return_strict asig =
let ia, t = asig.ret in
let ret' = mark_ia_strict ia true, t in
{ asig with ret = ret'}
(** Mark the return of the method_annotation with the given annotation. *)
let method_annotation_mark_return ann method_annotation =
let ia_ret, params = method_annotation in
let ia_ret' = mark_ia ann ia_ret true in
ia_ret', params

@ -18,9 +18,11 @@ val no_allocation : string
val nullable : string val nullable : string
val on_bind : string val on_bind : string
val performance_critical : string val performance_critical : string
val present : string
val for_non_ui_thread : string val for_non_ui_thread : string
val for_ui_thread : string val for_ui_thread : string
val guarded_by : string val guarded_by : string
val strict : string
val suppress_lint : string val suppress_lint : string
val thread_confined : string val thread_confined : string
val thread_safe : string val thread_safe : string
@ -28,40 +30,6 @@ val thread_safe_method : string
val ui_thread : string val ui_thread : string
val visibleForTesting : string val visibleForTesting : string
type annotation =
| Nullable
| Present
[@@deriving compare]
(** Method signature with annotations. *)
type annotated_signature = {
ret : Annot.Item.t * Typ.t; (** Annotated return type. *)
params: (Mangled.t * Annot.Item.t * Typ.t) list (** Annotated parameters. *)
} [@@deriving compare]
(** Check if the annotated signature is for a wrapper of an anonymous inner class method.
These wrappers have the same name as the original method, every type is Object, and the parameters
are called x0, x1, x2. *)
val annotated_signature_is_anonymous_inner_class_wrapper : annotated_signature -> Procname.t -> bool
(** Check if the given parameter has a Nullable annotation in the given signature *)
val param_is_nullable : Pvar.t -> annotated_signature -> bool
(** Mark the annotated signature with the given annotation map. *)
val annotated_signature_mark :
Procname.t -> annotation -> annotated_signature -> bool * bool list -> annotated_signature
(** Mark the return of the annotated signature with the given annotation. *)
val annotated_signature_mark_return :
annotation -> annotated_signature -> annotated_signature
(** Mark the return of the annotated signature @Strict. *)
val annotated_signature_mark_return_strict :
annotated_signature -> annotated_signature
(** Get a method signature with annotations from a proc_attributes. *)
val get_annotated_signature : ProcAttributes.t -> annotated_signature
(** [annot_ends_with annot ann_name] returns true if the class name of [annot], without the package, (** [annot_ends_with annot ann_name] returns true if the class name of [annot], without the package,
is equal to [ann_name] *) is equal to [ann_name] *)
val annot_ends_with : Annot.t -> string -> bool val annot_ends_with : Annot.t -> string -> bool
@ -145,12 +113,3 @@ val field_has_annot : Ident.fieldname -> StructTyp.t -> (Annot.Item.t -> bool) -
(** return true if the given predicate evaluates to true on some annotation of [struct_typ] *) (** return true if the given predicate evaluates to true on some annotation of [struct_typ] *)
val struct_typ_has_annot : StructTyp.t -> (Annot.Item.t -> bool) -> bool val struct_typ_has_annot : StructTyp.t -> (Annot.Item.t -> bool) -> bool
(** Mark the return of the method_annotation with the given annotation. *)
val method_annotation_mark_return :
annotation -> Annot.Method.t -> Annot.Method.t
(** Add the annotation to the item_annotation. *)
val mk_ia : annotation -> Annot.Item.t -> Annot.Item.t
val pp_annotated_signature : Procname.t -> Format.formatter -> annotated_signature -> unit

@ -0,0 +1,145 @@
(*
* Copyright (c) 2017 - 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.
*)
open! IStd
module F = Format
module L = Logging
type t = {
ret : Annot.Item.t * Typ.t;
params: (Mangled.t * Annot.Item.t * Typ.t) list;
} [@@deriving compare]
type annotation =
| Nullable
| Present
[@@deriving compare]
let ia_is ann ia = match ann with
| Nullable -> Annotations.ia_is_nullable ia
| Present -> Annotations.ia_is_present ia
let get proc_attributes : t =
let method_annotation = proc_attributes.ProcAttributes.method_annotation in
let formals = proc_attributes.ProcAttributes.formals in
let ret_type = proc_attributes.ProcAttributes.ret_type in
let (ia, ial0) = method_annotation in
let natl =
let rec extract ial parl = match ial, parl with
| ia :: ial', (name, typ) :: parl' ->
(name, ia, typ) :: extract ial' parl'
| [], (name, typ) :: parl' ->
(name, Annot.Item.empty, typ) :: extract [] parl'
| [], [] ->
[]
| _ :: _, [] ->
assert false in
IList.rev (extract (IList.rev ial0) (IList.rev formals)) in
let annotated_signature = { ret = (ia, ret_type); params = natl } in
annotated_signature
let param_is_nullable pvar ann_sig =
List.exists
~f:(fun (param, annot, _) ->
Mangled.equal param (Pvar.get_name pvar) && Annotations.ia_is_nullable annot)
ann_sig.params
let pp proc_name fmt annotated_signature =
let pp_ia fmt ia = if ia <> [] then F.fprintf fmt "%a " Annot.Item.pp ia in
let pp_annotated_param fmt (p, ia, t) =
F.fprintf fmt " %a%a %a" pp_ia ia (Typ.pp_full Pp.text) t Mangled.pp p in
let ia, ret_type = annotated_signature.ret in
F.fprintf fmt "%a%a %s (%a )"
pp_ia ia
(Typ.pp_full Pp.text) ret_type
(Procname.to_simplified_string proc_name)
(Pp.comma_seq pp_annotated_param) annotated_signature.params
let is_anonymous_inner_class_wrapper ann_sig proc_name =
let check_ret (ia, t) =
Annot.Item.is_empty ia && PatternMatch.type_is_object t in
let x_param_found = ref false in
let name_is_x_number name =
let name_str = Mangled.to_string name in
let len = String.length name_str in
len >= 2 &&
String.equal (String.sub name_str ~pos:0 ~len:1) "x" &&
let s = String.sub name_str ~pos:1 ~len:(len - 1) in
let is_int =
try
ignore (int_of_string s);
x_param_found := true;
true
with Failure _ -> false in
is_int in
let check_param (name, ia, t) =
if String.equal (Mangled.to_string name) "this" then true
else
name_is_x_number name &&
Annot.Item.is_empty ia &&
PatternMatch.type_is_object t in
Procname.java_is_anonymous_inner_class proc_name
&& check_ret ann_sig.ret
&& IList.for_all check_param ann_sig.params
&& !x_param_found
let mk_ann_str s = { Annot.class_name = s; parameters = [] }
let mk_ann = function
| Nullable -> mk_ann_str Annotations.nullable
| Present -> mk_ann_str Annotations.present
let mk_ia ann ia =
if ia_is ann ia then ia
else (mk_ann ann, true) :: ia
let mark_ia ann ia x =
if x then mk_ia ann ia else ia
let mk_ia_strict ia =
if Annotations.ia_get_strict ia <> None then ia
else (mk_ann_str Annotations.strict, true) :: ia
let mark_ia_strict ia x =
if x then mk_ia_strict ia else ia
let method_annotation_mark_return ann method_annotation =
let ia_ret, params = method_annotation in
let ia_ret' = mark_ia ann ia_ret true in
ia_ret', params
let mark proc_name ann asig (b, bs) =
let ia, t = asig.ret in
let ret' = mark_ia ann ia b, t in
let mark_param (s, ia, t) x =
let ia' = if x then mk_ia ann ia else ia in
(s, ia', t) in
let params' =
let fail () =
L.stdout
"INTERNAL ERROR: annotation for procedure %s has wrong number of arguments@."
(Procname.to_unique_id proc_name);
L.stdout " ANNOTATED SIGNATURE: %a@." (pp proc_name) asig;
assert false in
let rec combine l1 l2 = match l1, l2 with
| (p, ia, t):: l1', l2' when String.equal (Mangled.to_string p) "this" ->
(p, ia, t) :: combine l1' l2'
| (s, ia, t):: l1', x:: l2' ->
mark_param (s, ia, t) x :: combine l1' l2'
| [], _:: _ -> fail ()
| _:: _, [] -> fail ()
| [], [] -> [] in
combine asig.params bs in
{ ret = ret'; params = params'}
let mark_return ann asig =
let ia, t = asig.ret in
let ret' = mark_ia ann ia true, t in
{ asig with ret = ret'}
let mark_return_strict asig =
let ia, t = asig.ret in
let ret' = mark_ia_strict ia true, t in
{ asig with ret = ret'}

@ -0,0 +1,50 @@
(*
* Copyright (c) 2017 - 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.
*)
(** Method signature with annotations. *)
type t = {
ret : Annot.Item.t * Typ.t; (** Annotated return type. *)
params: (Mangled.t * Annot.Item.t * Typ.t) list; (** Annotated parameters. *)
} [@@deriving compare]
type annotation =
| Nullable
| Present
[@@deriving compare]
(** Check if the annotated signature is for a wrapper of an anonymous inner class method.
These wrappers have the same name as the original method, every type is Object, and the
parameters are called x0, x1, x2. *)
val is_anonymous_inner_class_wrapper : t -> Procname.t -> bool
(** Check if the given parameter has a Nullable annotation in the given signature *)
val param_is_nullable : Pvar.t -> t -> bool
(** Mark the return of the method_annotation with the given annotation. *)
val method_annotation_mark_return : annotation -> Annot.Method.t -> Annot.Method.t
(** Mark the annotated signature with the given annotation map. *)
val mark : Procname.t -> annotation -> t -> bool * bool list -> t
(** Mark the return of the annotated signature with the given annotation. *)
val mark_return : annotation -> t -> t
(** Mark the return of the annotated signature @Strict. *)
val mark_return_strict : t -> t
(** Get a method signature with annotations from a proc_attributes. *)
val get : ProcAttributes.t -> t
(** Add the annotation to the item_annotation. *)
val mk_ia : annotation -> Annot.Item.t -> Annot.Item.t
(** Pretty print a method signature with annotations. *)
val pp : Procname.t -> Format.formatter -> t -> unit

@ -78,7 +78,7 @@ struct
TypeState.add pvar (typ, ta, []) typestate in TypeState.add pvar (typ, ta, []) typestate in
let get_initial_typestate () = let get_initial_typestate () =
let typestate_empty = TypeState.empty Extension.ext in let typestate_empty = TypeState.empty Extension.ext in
IList.fold_left add_formal typestate_empty annotated_signature.Annotations.params in IList.fold_left add_formal typestate_empty annotated_signature.AnnotatedSignature.params in
(* Check the nullable flag computed for the return value and report inconsistencies. *) (* Check the nullable flag computed for the return value and report inconsistencies. *)
let check_return find_canonical_duplicate exit_node final_typestate ret_ia ret_type loc : unit = let check_return find_canonical_duplicate exit_node final_typestate ret_ia ret_type loc : unit =
@ -107,7 +107,7 @@ struct
let do_after_dataflow find_canonical_duplicate final_typestate = let do_after_dataflow find_canonical_duplicate final_typestate =
let exit_node = Procdesc.get_exit_node curr_pdesc in let exit_node = Procdesc.get_exit_node curr_pdesc in
let ia, ret_type = annotated_signature.Annotations.ret in let ia, ret_type = annotated_signature.AnnotatedSignature.ret in
check_return find_canonical_duplicate exit_node final_typestate ia ret_type proc_loc in check_return find_canonical_duplicate exit_node final_typestate ia ret_type proc_loc in
let module DFTypeCheck = MakeDF(struct let module DFTypeCheck = MakeDF(struct
@ -276,7 +276,7 @@ struct
let is_initializer proc_attributes = let is_initializer proc_attributes =
PatternMatch.method_is_initializer tenv proc_attributes || PatternMatch.method_is_initializer tenv proc_attributes ||
let ia, _ = let ia, _ =
(Models.get_modelled_annotated_signature proc_attributes).Annotations.ret in (Models.get_modelled_annotated_signature proc_attributes).AnnotatedSignature.ret in
Annotations.ia_is_initializer ia in Annotations.ia_is_initializer ia in
let initializers_current_class = let initializers_current_class =
pname_and_pdescs_with pname_and_pdescs_with
@ -357,9 +357,7 @@ struct
let loc = Procdesc.get_loc proc_desc in let loc = Procdesc.get_loc proc_desc in
let linereader = Printer.LineReader.create () in let linereader = Printer.LineReader.create () in
if Config.eradicate_verbose then if Config.eradicate_verbose then
L.stdout "%a@." L.stdout "%a@." (AnnotatedSignature.pp proc_name) annotated_signature;
(Annotations.pp_annotated_signature proc_name)
annotated_signature;
callback2 callback2
calls_this checks callback_args annotated_signature linereader loc calls_this checks callback_args annotated_signature linereader loc

@ -30,7 +30,7 @@ let get_field_annotation tenv fn typ =
(* outside of Eradicate in some other way *) (* outside of Eradicate in some other way *)
if (Models.Inference.enabled || not Config.eradicate) if (Models.Inference.enabled || not Config.eradicate)
&& Models.Inference.field_is_marked fn && Models.Inference.field_is_marked fn
then Annotations.mk_ia Annotations.Nullable ia then AnnotatedSignature.mk_ia AnnotatedSignature.Nullable ia
else ia in else ia in
Some (t, ia') Some (t, ia')
@ -63,7 +63,7 @@ let is_virtual = function
(** Check an access (read or write) to a field. *) (** Check an access (read or write) to a field. *)
let check_field_access tenv let check_field_access tenv
find_canonical_duplicate curr_pname node instr_ref exp fname ta loc : unit = find_canonical_duplicate curr_pname node instr_ref exp fname ta loc : unit =
if TypeAnnotation.get_value Annotations.Nullable ta then if TypeAnnotation.get_value AnnotatedSignature.Nullable ta then
let origin_descr = TypeAnnotation.descr_origin tenv ta in let origin_descr = TypeAnnotation.descr_origin tenv ta in
report_error tenv report_error tenv
find_canonical_duplicate find_canonical_duplicate
@ -82,7 +82,7 @@ let check_array_access tenv
ta ta
loc loc
indexed = indexed =
if TypeAnnotation.get_value Annotations.Nullable ta then if TypeAnnotation.get_value AnnotatedSignature.Nullable ta then
let origin_descr = TypeAnnotation.descr_origin tenv ta in let origin_descr = TypeAnnotation.descr_origin tenv ta in
report_error tenv report_error tenv
find_canonical_duplicate find_canonical_duplicate
@ -108,7 +108,7 @@ let check_condition tenv case_zero find_canonical_duplicate curr_pdesc
node e typ ta true_branch from_call idenv linereader loc instr_ref : unit = node e typ ta true_branch from_call idenv linereader loc instr_ref : unit =
let is_fun_nonnull ta = match TypeAnnotation.get_origin ta with let is_fun_nonnull ta = match TypeAnnotation.get_origin ta with
| TypeOrigin.Proc proc_origin -> | TypeOrigin.Proc proc_origin ->
let (ia, _) = proc_origin.TypeOrigin.annotated_signature.Annotations.ret in let (ia, _) = proc_origin.TypeOrigin.annotated_signature.AnnotatedSignature.ret in
Annotations.ia_is_nonnull ia Annotations.ia_is_nonnull ia
| _ -> false in | _ -> false in
@ -144,7 +144,7 @@ let check_condition tenv case_zero find_canonical_duplicate curr_pdesc
let is_temp = Idenv.exp_is_temp idenv e in let is_temp = Idenv.exp_is_temp idenv e in
let nonnull = is_fun_nonnull ta in let nonnull = is_fun_nonnull ta in
let should_report = let should_report =
not (TypeAnnotation.get_value Annotations.Nullable ta) && not (TypeAnnotation.get_value AnnotatedSignature.Nullable ta) &&
(Config.eradicate_condition_redundant || nonnull) && (Config.eradicate_condition_redundant || nonnull) &&
true_branch && true_branch &&
(not is_temp || nonnull) && (not is_temp || nonnull) &&
@ -174,25 +174,25 @@ let check_field_assignment tenv
let curr_pname = Procdesc.get_proc_name curr_pdesc in let curr_pname = Procdesc.get_proc_name curr_pdesc in
let (t_lhs, ta_lhs, _) = let (t_lhs, ta_lhs, _) =
typecheck_expr node instr_ref curr_pdesc typestate exp_lhs typecheck_expr node instr_ref curr_pdesc typestate exp_lhs
(typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, [loc]) loc in (typ, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, [loc]) loc in
let (_, ta_rhs, _) = let (_, ta_rhs, _) =
typecheck_expr node instr_ref curr_pdesc typestate exp_rhs typecheck_expr node instr_ref curr_pdesc typestate exp_rhs
(typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, [loc]) loc in (typ, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, [loc]) loc in
let should_report_nullable = let should_report_nullable =
let field_is_field_injector_readwrite () = match t_ia_opt with let field_is_field_injector_readwrite () = match t_ia_opt with
| Some (_, ia) -> | Some (_, ia) ->
Annotations.ia_is_field_injector_readwrite ia Annotations.ia_is_field_injector_readwrite ia
| _ -> | _ ->
false in false in
not (TypeAnnotation.get_value Annotations.Nullable ta_lhs) && not (TypeAnnotation.get_value AnnotatedSignature.Nullable ta_lhs) &&
TypeAnnotation.get_value Annotations.Nullable ta_rhs && TypeAnnotation.get_value AnnotatedSignature.Nullable ta_rhs &&
PatternMatch.type_is_class t_lhs && PatternMatch.type_is_class t_lhs &&
not (Ident.java_fieldname_is_outer_instance fname) && not (Ident.java_fieldname_is_outer_instance fname) &&
not (field_is_field_injector_readwrite ()) in not (field_is_field_injector_readwrite ()) in
let should_report_absent = let should_report_absent =
Config.eradicate_optional_present && Config.eradicate_optional_present &&
TypeAnnotation.get_value Annotations.Present ta_lhs && TypeAnnotation.get_value AnnotatedSignature.Present ta_lhs &&
not (TypeAnnotation.get_value Annotations.Present ta_rhs) && not (TypeAnnotation.get_value AnnotatedSignature.Present ta_rhs) &&
not (Ident.java_fieldname_is_outer_instance fname) in not (Ident.java_fieldname_is_outer_instance fname) in
let should_report_mutable = let should_report_mutable =
let field_is_mutable () = match t_ia_opt with let field_is_mutable () = match t_ia_opt with
@ -204,7 +204,10 @@ let check_field_assignment tenv
not (field_is_mutable ()) in not (field_is_mutable ()) in
if should_report_nullable || should_report_absent then if should_report_nullable || should_report_absent then
begin begin
let ann = if should_report_nullable then Annotations.Nullable else Annotations.Present in let ann =
if should_report_nullable
then AnnotatedSignature.Nullable
else AnnotatedSignature.Present in
if Models.Inference.enabled then Models.Inference.field_add_nullable_annotation fname; if Models.Inference.enabled then Models.Inference.field_add_nullable_annotation fname;
let origin_descr = TypeAnnotation.descr_origin tenv ta_rhs in let origin_descr = TypeAnnotation.descr_origin tenv ta_rhs in
report_error tenv report_error tenv
@ -281,7 +284,7 @@ let check_constructor_initialization tenv
final_type_annotation_with final_type_annotation_with
true true
(Lazy.force final_constructor_typestates) (Lazy.force final_constructor_typestates)
(fun ta -> TypeAnnotation.get_value Annotations.Nullable ta) in (fun ta -> TypeAnnotation.get_value AnnotatedSignature.Nullable ta) in
let should_check_field_initialization = let should_check_field_initialization =
let in_current_class = let in_current_class =
@ -330,8 +333,8 @@ let spec_make_return_nullable curr_pname =
| Some summary -> | Some summary ->
let proc_attributes = Specs.get_attributes summary in let proc_attributes = Specs.get_attributes summary in
let method_annotation = proc_attributes.ProcAttributes.method_annotation in let method_annotation = proc_attributes.ProcAttributes.method_annotation in
let method_annotation' = Annotations.method_annotation_mark_return let method_annotation' = AnnotatedSignature.method_annotation_mark_return
Annotations.Nullable method_annotation in AnnotatedSignature.Nullable method_annotation in
let proc_attributes' = let proc_attributes' =
{ proc_attributes with { proc_attributes with
ProcAttributes.method_annotation = method_annotation' } in ProcAttributes.method_annotation = method_annotation' } in
@ -351,8 +354,8 @@ let check_return_annotation tenv
let ret_annotated_nonnull = Annotations.ia_is_nonnull ret_ia in let ret_annotated_nonnull = Annotations.ia_is_nonnull ret_ia in
match ret_range with match ret_range with
| Some (_, final_ta, _) -> | Some (_, final_ta, _) ->
let final_nullable = TypeAnnotation.get_value Annotations.Nullable final_ta in let final_nullable = TypeAnnotation.get_value AnnotatedSignature.Nullable final_ta in
let final_present = TypeAnnotation.get_value Annotations.Present final_ta in let final_present = TypeAnnotation.get_value AnnotatedSignature.Present final_ta in
let origin_descr = TypeAnnotation.descr_origin tenv final_ta in let origin_descr = TypeAnnotation.descr_origin tenv final_ta in
let return_not_nullable = let return_not_nullable =
final_nullable && final_nullable &&
@ -379,9 +382,9 @@ let check_return_annotation tenv
if return_not_nullable || return_value_not_present then if return_not_nullable || return_value_not_present then
begin begin
let ann = let ann =
if return_not_nullable then Annotations.Nullable else Annotations.Present in if return_not_nullable
then AnnotatedSignature.Nullable
else AnnotatedSignature.Present in
report_error tenv report_error tenv
find_canonical_duplicate find_canonical_duplicate
(TypeErr.Return_annotation_inconsistent (ann, curr_pname, origin_descr)) (TypeErr.Return_annotation_inconsistent (ann, curr_pname, origin_descr))
@ -416,15 +419,18 @@ let check_call_receiver tenv
| ((original_this_e, this_e), typ) :: _ -> | ((original_this_e, this_e), typ) :: _ ->
let (_, this_ta, _) = let (_, this_ta, _) =
typecheck_expr tenv node instr_ref curr_pdesc typestate this_e typecheck_expr tenv node instr_ref curr_pdesc typestate this_e
(typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, []) loc in (typ, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, []) loc in
let null_method_call = TypeAnnotation.get_value Annotations.Nullable this_ta in let null_method_call = TypeAnnotation.get_value AnnotatedSignature.Nullable this_ta in
let optional_get_on_absent = let optional_get_on_absent =
Config.eradicate_optional_present && Config.eradicate_optional_present &&
Models.is_optional_get callee_pname && Models.is_optional_get callee_pname &&
not (TypeAnnotation.get_value Annotations.Present this_ta) in not (TypeAnnotation.get_value AnnotatedSignature.Present this_ta) in
if null_method_call || optional_get_on_absent then if null_method_call || optional_get_on_absent then
begin begin
let ann = if null_method_call then Annotations.Nullable else Annotations.Present in let ann =
if null_method_call
then AnnotatedSignature.Nullable
else AnnotatedSignature.Present in
let descr = explain_expr tenv node original_this_e in let descr = explain_expr tenv node original_this_e in
let origin_descr = TypeAnnotation.descr_origin tenv this_ta in let origin_descr = TypeAnnotation.descr_origin tenv this_ta in
report_error tenv report_error tenv
@ -450,24 +456,24 @@ let check_call_parameters tenv
let formal_is_present = Annotations.ia_is_present ia1 in let formal_is_present = Annotations.ia_is_present ia1 in
let (_, ta2, _) = let (_, ta2, _) =
typecheck_expr node instr_ref curr_pdesc typestate e2 typecheck_expr node instr_ref curr_pdesc typestate e2
(t2, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, []) loc in (t2, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, []) loc in
let parameter_not_nullable = let parameter_not_nullable =
not param_is_this && not param_is_this &&
PatternMatch.type_is_class t1 && PatternMatch.type_is_class t1 &&
not formal_is_nullable && not formal_is_nullable &&
TypeAnnotation.get_value Annotations.Nullable ta2 in TypeAnnotation.get_value AnnotatedSignature.Nullable ta2 in
let parameter_absent = let parameter_absent =
Config.eradicate_optional_present && Config.eradicate_optional_present &&
not param_is_this && not param_is_this &&
PatternMatch.type_is_class t1 && PatternMatch.type_is_class t1 &&
formal_is_present && formal_is_present &&
not (TypeAnnotation.get_value Annotations.Present ta2) in not (TypeAnnotation.get_value AnnotatedSignature.Present ta2) in
if parameter_not_nullable || parameter_absent then if parameter_not_nullable || parameter_absent then
begin begin
let ann = let ann =
if parameter_not_nullable if parameter_not_nullable
then Annotations.Nullable then AnnotatedSignature.Nullable
else Annotations.Present in else AnnotatedSignature.Present in
let description = let description =
match explain_expr tenv node orig_e2 with match explain_expr tenv node orig_e2 with
| Some descr -> descr | Some descr -> descr
@ -511,10 +517,10 @@ let check_overridden_annotations
let check_return overriden_proc_name overriden_signature = let check_return overriden_proc_name overriden_signature =
let ret_is_nullable = let ret_is_nullable =
let ia, _ = annotated_signature.Annotations.ret in let ia, _ = annotated_signature.AnnotatedSignature.ret in
Annotations.ia_is_nullable ia Annotations.ia_is_nullable ia
and ret_overridden_nullable = and ret_overridden_nullable =
let overriden_ia, _ = overriden_signature.Annotations.ret in let overriden_ia, _ = overriden_signature.AnnotatedSignature.ret in
Annotations.ia_is_nullable overriden_ia in Annotations.ia_is_nullable overriden_ia in
if ret_is_nullable && not ret_overridden_nullable then if ret_is_nullable && not ret_overridden_nullable then
report_error tenv report_error tenv
@ -539,8 +545,8 @@ let check_overridden_annotations
(pos + 1) in (pos + 1) in
(* TODO (#5280249): investigate why argument lists can be of different length *) (* TODO (#5280249): investigate why argument lists can be of different length *)
let current_params = annotated_signature.Annotations.params let current_params = annotated_signature.AnnotatedSignature.params
and overridden_params = overriden_signature.Annotations.params in and overridden_params = overriden_signature.AnnotatedSignature.params in
let initial_pos = if is_virtual current_params then 0 else 1 in let initial_pos = if is_virtual current_params then 0 else 1 in
if Int.equal (IList.length current_params) (IList.length overridden_params) then if Int.equal (IList.length current_params) (IList.length overridden_params) then
ignore (IList.fold_left2 compare initial_pos current_params overridden_params) in ignore (IList.fold_left2 compare initial_pos current_params overridden_params) in

@ -103,7 +103,7 @@ let table_has_procedure table proc_name =
(** Return the annotated signature of the procedure, taking into account models. *) (** Return the annotated signature of the procedure, taking into account models. *)
let get_modelled_annotated_signature proc_attributes = let get_modelled_annotated_signature proc_attributes =
let proc_name = proc_attributes.ProcAttributes.proc_name in let proc_name = proc_attributes.ProcAttributes.proc_name in
let annotated_signature = Annotations.get_annotated_signature proc_attributes in let annotated_signature = AnnotatedSignature.get proc_attributes in
let proc_id = Procname.to_unique_id proc_name in let proc_id = Procname.to_unique_id proc_name in
let infer_parameters ann_sig = let infer_parameters ann_sig =
let mark_par = let mark_par =
@ -113,19 +113,19 @@ let get_modelled_annotated_signature proc_attributes =
| None -> ann_sig | None -> ann_sig
| Some bs -> | Some bs ->
let mark = (false, bs) in let mark = (false, bs) in
Annotations.annotated_signature_mark proc_name Annotations.Nullable ann_sig mark in AnnotatedSignature.mark proc_name AnnotatedSignature.Nullable ann_sig mark in
let infer_return ann_sig = let infer_return ann_sig =
let mark_r = let mark_r =
Inference.enabled && Inference.enabled &&
Inference.proc_return_is_marked proc_name in Inference.proc_return_is_marked proc_name in
if mark_r if mark_r
then Annotations.annotated_signature_mark_return Annotations.Nullable ann_sig then AnnotatedSignature.mark_return AnnotatedSignature.Nullable ann_sig
else ann_sig in else ann_sig in
let lookup_models_nullable ann_sig = let lookup_models_nullable ann_sig =
if use_models then if use_models then
try try
let mark = Hashtbl.find annotated_table_nullable proc_id in let mark = Hashtbl.find annotated_table_nullable proc_id in
Annotations.annotated_signature_mark proc_name Annotations.Nullable ann_sig mark AnnotatedSignature.mark proc_name AnnotatedSignature.Nullable ann_sig mark
with Not_found -> with Not_found ->
ann_sig ann_sig
else ann_sig in else ann_sig in
@ -133,7 +133,7 @@ let get_modelled_annotated_signature proc_attributes =
if use_models then if use_models then
try try
let mark = Hashtbl.find annotated_table_present proc_id in let mark = Hashtbl.find annotated_table_present proc_id in
Annotations.annotated_signature_mark proc_name Annotations.Present ann_sig mark AnnotatedSignature.mark proc_name AnnotatedSignature.Present ann_sig mark
with Not_found -> with Not_found ->
ann_sig ann_sig
else ann_sig in else ann_sig in
@ -141,7 +141,7 @@ let get_modelled_annotated_signature proc_attributes =
if use_models if use_models
&& Hashtbl.mem annotated_table_strict proc_id && Hashtbl.mem annotated_table_strict proc_id
then then
Annotations.annotated_signature_mark_return_strict ann_sig AnnotatedSignature.mark_return_strict ann_sig
else else
ann_sig in ann_sig in

@ -15,10 +15,10 @@ module P = Printf
(** Module to represent annotations on types. *) (** Module to represent annotations on types. *)
module AnnotationsMap = Caml.Map.Make ( module AnnotationsMap = Caml.Map.Make (
struct struct
open Annotations type t = AnnotatedSignature.annotation [@@deriving compare]
type t = annotation [@@deriving compare]
end) end)
type t = { type t = {
@ -40,16 +40,22 @@ let set_value ann b ta =
map = AnnotationsMap.add ann b ta.map; } map = AnnotationsMap.add ann b ta.map; }
let get_nullable = let get_nullable =
get_value Annotations.Nullable get_value AnnotatedSignature.Nullable
let get_present = let get_present =
get_value Annotations.Present get_value Present
let set_nullable b = let set_nullable b =
set_value Annotations.Nullable b set_value Nullable b
let set_present b = let set_present b =
set_value Annotations.Present b set_value Present b
let descr_origin tenv ta =
let descr_opt = TypeOrigin.get_description tenv ta.origin in
match descr_opt with
| None -> ("", None, None)
| Some (str, loc_opt, sig_opt) -> ("(Origin: " ^ str ^ ")", loc_opt, sig_opt)
let to_string ta = let to_string ta =
let nullable_s = if get_nullable ta then " @Nullable" else "" in let nullable_s = if get_nullable ta then " @Nullable" else "" in
@ -79,16 +85,10 @@ let origin_is_fun_library ta = match get_origin ta with
proc_origin.TypeOrigin.is_library proc_origin.TypeOrigin.is_library
| _ -> false | _ -> false
let descr_origin tenv ta : TypeErr.origin_descr =
let descr_opt = TypeOrigin.get_description tenv ta.origin in
match descr_opt with
| None -> ("", None, None)
| Some (str, loc_opt, sig_opt) -> ("(Origin: " ^ str ^ ")", loc_opt, sig_opt)
let const annotation b origin = let const annotation b origin =
let nullable, present = match annotation with let nullable, present = match annotation with
| Annotations.Nullable -> b, false | AnnotatedSignature.Nullable -> b, false
| Annotations.Present -> false, b in | AnnotatedSignature.Present -> false, b in
let ta = let ta =
{ origin; { origin;
map = AnnotationsMap.empty; map = AnnotationsMap.empty;
@ -99,5 +99,5 @@ let with_origin ta o =
{ ta with origin = o } { ta with origin = o }
let from_item_annotation ia origin = let from_item_annotation ia origin =
let ta = const Annotations.Nullable (Annotations.ia_is_nullable ia) origin in let ta = const Nullable (Annotations.ia_is_nullable ia) origin in
set_value Annotations.Present (Annotations.ia_is_present ia) ta set_value Present (Annotations.ia_is_present ia) ta

@ -15,16 +15,16 @@ type t [@@deriving compare]
val equal : t -> t -> bool val equal : t -> t -> bool
val const : Annotations.annotation -> bool -> TypeOrigin.t -> t val const : AnnotatedSignature.annotation -> bool -> TypeOrigin.t -> t
(** Human-readable description of the origin of a nullable value. *) (** Human-readable description of the origin of a nullable value. *)
val descr_origin : Tenv.t -> t -> TypeErr.origin_descr val descr_origin : Tenv.t -> t -> TypeErr.origin_descr
val from_item_annotation : Annot.Item.t -> TypeOrigin.t -> t val from_item_annotation : Annot.Item.t -> TypeOrigin.t -> t
val get_origin : t -> TypeOrigin.t val get_origin : t -> TypeOrigin.t
val get_value : Annotations.annotation -> t -> bool val get_value : AnnotatedSignature.annotation -> t -> bool
val join : t -> t -> t option val join : t -> t -> t option
val origin_is_fun_library : t -> bool val origin_is_fun_library : t -> bool
val set_value : Annotations.annotation -> bool -> t -> t val set_value : AnnotatedSignature.annotation -> bool -> t -> t
val to_string : t -> string val to_string : t -> string
val with_origin : t -> TypeOrigin.t -> t val with_origin : t -> TypeOrigin.t -> t

@ -48,7 +48,7 @@ module ComplexExpressions = struct
| Some proc_attributes -> | Some proc_attributes ->
let annotated_signature = let annotated_signature =
Models.get_modelled_annotated_signature proc_attributes in Models.get_modelled_annotated_signature proc_attributes in
let ret_ann, _ = annotated_signature.Annotations.ret in let ret_ann, _ = annotated_signature.AnnotatedSignature.ret in
Annotations.ia_is_false_on_null ret_ann Annotations.ia_is_false_on_null ret_ann
| None -> | None ->
false false
@ -59,7 +59,7 @@ module ComplexExpressions = struct
| Some proc_attributes -> | Some proc_attributes ->
let annotated_signature = let annotated_signature =
Models.get_modelled_annotated_signature proc_attributes in Models.get_modelled_annotated_signature proc_attributes in
let ret_ann, _ = annotated_signature.Annotations.ret in let ret_ann, _ = annotated_signature.AnnotatedSignature.ret in
Annotations.ia_is_true_on_null ret_ann Annotations.ia_is_true_on_null ret_ann
| None -> | None ->
false in false in
@ -170,7 +170,7 @@ let rec typecheck_expr
| Exp.Const (Const.Cint i) when IntLit.iszero i -> | Exp.Const (Const.Cint i) when IntLit.iszero i ->
let (typ, _, locs) = tr_default in let (typ, _, locs) = tr_default in
if PatternMatch.type_is_class typ if PatternMatch.type_is_class typ
then (typ, TypeAnnotation.const Annotations.Nullable true (TypeOrigin.Const loc), locs) then (typ, TypeAnnotation.const AnnotatedSignature.Nullable true (TypeOrigin.Const loc), locs)
else else
let t, ta, ll = tr_default in let t, ta, ll = tr_default in
(t, TypeAnnotation.with_origin ta (TypeOrigin.Const loc), ll) (t, TypeAnnotation.with_origin ta (TypeOrigin.Const loc), ll)
@ -181,13 +181,14 @@ let rec typecheck_expr
typestate e1 tr_default loc typestate e1 tr_default loc
| Exp.Const _ -> | Exp.Const _ ->
let (typ, _, locs) = tr_default in let (typ, _, locs) = tr_default in
(typ, TypeAnnotation.const Annotations.Nullable false (TypeOrigin.Const loc), locs) (typ, TypeAnnotation.const AnnotatedSignature.Nullable false (TypeOrigin.Const loc), locs)
| Exp.Lfield (exp, fn, typ) -> | Exp.Lfield (exp, fn, typ) ->
let _, _, locs = tr_default in let _, _, locs = tr_default in
let (_, ta, locs') = let (_, ta, locs') =
typecheck_expr typecheck_expr
find_canonical_duplicate visited checks tenv node instr_ref curr_pdesc typestate exp find_canonical_duplicate visited checks tenv node instr_ref curr_pdesc typestate exp
(typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, locs) loc in (typ, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, locs) loc
in
let tr_new = match EradicateChecks.get_field_annotation tenv fn typ with let tr_new = match EradicateChecks.get_field_annotation tenv fn typ with
| Some (t, ia) -> | Some (t, ia) ->
( (
@ -345,7 +346,7 @@ let typecheck_instr
let is_parameter_field pvar = (* parameter.field *) let is_parameter_field pvar = (* parameter.field *)
let name = Pvar.get_name pvar in let name = Pvar.get_name pvar in
let filter (s, _, _) = Mangled.equal s name in let filter (s, _, _) = Mangled.equal s name in
List.exists ~f:filter annotated_signature.Annotations.params in List.exists ~f:filter annotated_signature.AnnotatedSignature.params in
let is_static_field pvar = (* static field *) let is_static_field pvar = (* static field *)
Pvar.is_global pvar in Pvar.is_global pvar in
@ -426,9 +427,9 @@ let typecheck_instr
let drop_unchecked_signature_params proc_attributes annotated_signature = let drop_unchecked_signature_params proc_attributes annotated_signature =
if Procname.is_constructor (proc_attributes.ProcAttributes.proc_name) && if Procname.is_constructor (proc_attributes.ProcAttributes.proc_name) &&
proc_attributes.ProcAttributes.is_synthetic_method then proc_attributes.ProcAttributes.is_synthetic_method then
IList.drop_last 1 annotated_signature.Annotations.params IList.drop_last 1 annotated_signature.AnnotatedSignature.params
else else
annotated_signature.Annotations.params in annotated_signature.AnnotatedSignature.params in
let is_return pvar = let is_return pvar =
let ret_pvar = Procdesc.get_ret_var curr_pdesc in let ret_pvar = Procdesc.get_ret_var curr_pdesc in
@ -460,7 +461,7 @@ let typecheck_instr
typecheck_expr typecheck_expr
find_canonical_duplicate calls_this checks tenv node instr_ref find_canonical_duplicate calls_this checks tenv node instr_ref
curr_pdesc typestate1 exp1 curr_pdesc typestate1 exp1
(typ1, TypeAnnotation.const Annotations.Nullable false origin1, [loc1]) (typ1, TypeAnnotation.const AnnotatedSignature.Nullable false origin1, [loc1])
loc1 in loc1 in
(* check if there are errors in exp1 *) (* check if there are errors in exp1 *)
@ -513,7 +514,7 @@ let typecheck_instr
Procname.equal pn BuiltinDecl.__new_array -> Procname.equal pn BuiltinDecl.__new_array ->
TypeState.add_id TypeState.add_id
id id
(typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.New, [loc]) (typ, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.New, [loc])
typestate (* new never returns null *) typestate (* new never returns null *)
| Sil.Call (Some (id, _), Exp.Const (Const.Cfun pn), (e, typ):: _, loc, _) | Sil.Call (Some (id, _), Exp.Const (Const.Cfun pn), (e, typ):: _, loc, _)
when Procname.equal pn BuiltinDecl.__cast -> when Procname.equal pn BuiltinDecl.__cast ->
@ -535,7 +536,7 @@ let typecheck_instr
curr_pdesc curr_pdesc
typestate typestate
array_exp array_exp
(t, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, [loc]) (t, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, [loc])
loc in loc in
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_array_access tenv EradicateChecks.check_array_access tenv
@ -552,7 +553,7 @@ let typecheck_instr
id id
( (
Typ.Tint (Typ.IInt), Typ.Tint (Typ.IInt),
TypeAnnotation.const Annotations.Nullable false TypeOrigin.New, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.New,
[loc] [loc]
) )
typestate typestate
@ -609,7 +610,7 @@ let typecheck_instr
match ret_id with match ret_id with
| None -> typestate' | None -> typestate'
| Some (id, _) -> | Some (id, _) ->
let (ia, ret_typ) = annotated_signature.Annotations.ret in let (ia, ret_typ) = annotated_signature.AnnotatedSignature.ret in
let is_library = Specs.proc_is_library callee_attributes in let is_library = Specs.proc_is_library callee_attributes in
let origin = TypeOrigin.Proc let origin = TypeOrigin.Proc
{ {
@ -636,7 +637,7 @@ let typecheck_instr
| Some (t, ta, _) -> | Some (t, ta, _) ->
let should_report = let should_report =
Config.eradicate_condition_redundant && Config.eradicate_condition_redundant &&
not (TypeAnnotation.get_value Annotations.Nullable ta) && not (TypeAnnotation.get_value AnnotatedSignature.Nullable ta) &&
not (TypeAnnotation.origin_is_fun_library ta) in not (TypeAnnotation.origin_is_fun_library ta) in
if checks.eradicate && should_report then if checks.eradicate && should_report then
begin begin
@ -650,7 +651,7 @@ let typecheck_instr
end; end;
TypeState.add TypeState.add
pvar pvar
(t, TypeAnnotation.const Annotations.Nullable false TypeOrigin.ONone, [loc]) (t, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, [loc])
typestate'' typestate''
| None -> | None ->
typestate' in typestate' in
@ -700,7 +701,7 @@ let typecheck_instr
begin begin
match convert_complex_exp_to_pvar cond_node false cond_e typestate' loc with match convert_complex_exp_to_pvar cond_node false cond_e typestate' loc with
| Exp.Lvar pvar', _ -> | Exp.Lvar pvar', _ ->
set_flag pvar' Annotations.Nullable false set_flag pvar' AnnotatedSignature.Nullable false
| _ -> () | _ -> ()
end end
| _ -> () in | _ -> () in
@ -708,7 +709,7 @@ let typecheck_instr
let handle_optional_isPresent node' e = let handle_optional_isPresent node' e =
match convert_complex_exp_to_pvar node' false e typestate' loc with match convert_complex_exp_to_pvar node' false e typestate' loc with
| Exp.Lvar pvar', _ -> | Exp.Lvar pvar', _ ->
set_flag pvar' Annotations.Present true set_flag pvar' AnnotatedSignature.Present true
| _ -> () in | _ -> () in
match call_params with match call_params with
| ((_, Exp.Lvar pvar), _):: _ -> | ((_, Exp.Lvar pvar), _):: _ ->
@ -956,8 +957,8 @@ let typecheck_instr
match from_call with match from_call with
| EradicateChecks.From_is_true_on_null -> | EradicateChecks.From_is_true_on_null ->
(* if f returns true on null, then false branch implies != null *) (* if f returns true on null, then false branch implies != null *)
if TypeAnnotation.get_value Annotations.Nullable ta if TypeAnnotation.get_value AnnotatedSignature.Nullable ta
then set_flag e' Annotations.Nullable false typestate2 then set_flag e' AnnotatedSignature.Nullable false typestate2
else typestate2 else typestate2
| _ -> | _ ->
typestate2 typestate2
@ -999,8 +1000,8 @@ let typecheck_instr
begin begin
match from_call with match from_call with
| EradicateChecks.From_optional_isPresent -> | EradicateChecks.From_optional_isPresent ->
if not (TypeAnnotation.get_value Annotations.Present ta) if not (TypeAnnotation.get_value AnnotatedSignature.Present ta)
then set_flag e' Annotations.Present true typestate2 then set_flag e' AnnotatedSignature.Present true typestate2
else typestate2 else typestate2
| EradicateChecks.From_is_true_on_null -> | EradicateChecks.From_is_true_on_null ->
typestate2 typestate2
@ -1008,8 +1009,8 @@ let typecheck_instr
| EradicateChecks.From_containsKey | EradicateChecks.From_containsKey
| EradicateChecks.From_instanceof | EradicateChecks.From_instanceof
| EradicateChecks.From_is_false_on_null -> | EradicateChecks.From_is_false_on_null ->
if TypeAnnotation.get_value Annotations.Nullable ta then if TypeAnnotation.get_value AnnotatedSignature.Nullable ta then
set_flag e' Annotations.Nullable false typestate2 set_flag e' AnnotatedSignature.Nullable false typestate2
else typestate2 else typestate2
end end

@ -30,5 +30,5 @@ val typecheck_node :
Tenv.t -> 'a TypeState.ext -> Tenv.t -> 'a TypeState.ext ->
bool ref -> checks -> Idenv.t -> bool ref -> checks -> Idenv.t ->
get_proc_desc -> Procname.t -> Procdesc.t -> get_proc_desc -> Procname.t -> Procdesc.t ->
find_canonical_duplicate -> Annotations.annotated_signature -> 'a TypeState.t -> find_canonical_duplicate -> AnnotatedSignature.t -> 'a TypeState.t ->
Procdesc.Node.t -> Printer.LineReader.t -> 'a TypeState.t list * 'a TypeState.t list Procdesc.Node.t -> Printer.LineReader.t -> 'a TypeState.t list * 'a TypeState.t list

@ -50,13 +50,13 @@ end (* InstrRef *)
type origin_descr = type origin_descr =
string * string *
Location.t option * Location.t option *
Annotations.annotated_signature option (* callee signature *) AnnotatedSignature.t option (* callee signature *)
(* ignore origin descr *) (* ignore origin descr *)
let compare_origin_descr _ _ = 0 let compare_origin_descr _ _ = 0
type parameter_not_nullable = type parameter_not_nullable =
Annotations.annotation * AnnotatedSignature.annotation *
string * (* description *) string * (* description *)
int * (* parameter number *) int * (* parameter number *)
Procname.t * Procname.t *
@ -71,13 +71,13 @@ type err_instance =
| Inconsistent_subclass_parameter_annotation of string * int * Procname.t * Procname.t | Inconsistent_subclass_parameter_annotation of string * int * Procname.t * Procname.t
| Field_not_initialized of Ident.fieldname * Procname.t | Field_not_initialized of Ident.fieldname * Procname.t
| Field_not_mutable of Ident.fieldname * origin_descr | Field_not_mutable of Ident.fieldname * origin_descr
| Field_annotation_inconsistent of Annotations.annotation * Ident.fieldname * origin_descr | Field_annotation_inconsistent of AnnotatedSignature.annotation * Ident.fieldname * origin_descr
| Field_over_annotated of Ident.fieldname * Procname.t | Field_over_annotated of Ident.fieldname * Procname.t
| Null_field_access of string option * Ident.fieldname * origin_descr * bool | Null_field_access of string option * Ident.fieldname * origin_descr * bool
| Call_receiver_annotation_inconsistent | Call_receiver_annotation_inconsistent
of Annotations.annotation * string option * Procname.t * origin_descr of AnnotatedSignature.annotation * string option * Procname.t * origin_descr
| Parameter_annotation_inconsistent of parameter_not_nullable | Parameter_annotation_inconsistent of parameter_not_nullable
| Return_annotation_inconsistent of Annotations.annotation * Procname.t * origin_descr | Return_annotation_inconsistent of AnnotatedSignature.annotation * Procname.t * origin_descr
| Return_over_annotated of Procname.t | Return_over_annotated of Procname.t
[@@deriving compare] [@@deriving compare]
@ -183,12 +183,12 @@ let add_err find_canonical_duplicate err_instance instr_ref_opt loc =
end end
module Strict = struct module Strict = struct
let method_get_strict signature = let method_get_strict (signature : AnnotatedSignature.t) =
let (ia, _) = signature.Annotations.ret in let (ia, _) = signature.ret in
Annotations.ia_get_strict ia Annotations.ia_get_strict ia
let this_type_get_strict tenv signature = let this_type_get_strict tenv (signature : AnnotatedSignature.t) =
match signature.Annotations.params with match signature.params with
| (p, _, this_type):: _ when String.equal (Mangled.to_string p) "this" -> | (p, _, this_type):: _ when String.equal (Mangled.to_string p) "this" ->
begin begin
match PatternMatch.type_get_annotation tenv this_type with match PatternMatch.type_get_annotation tenv this_type with
@ -215,10 +215,10 @@ module Strict = struct
(* with parameters. A method is Strict if it or its class are annotated @Strict. *) (* with parameters. A method is Strict if it or its class are annotated @Strict. *)
let err_instance_get_strict tenv err_instance : Annot.t option = let err_instance_get_strict tenv err_instance : Annot.t option =
match err_instance with match err_instance with
| Call_receiver_annotation_inconsistent (Annotations.Nullable, _, _, origin_descr) | Call_receiver_annotation_inconsistent (AnnotatedSignature.Nullable, _, _, origin_descr)
| Null_field_access (_, _, origin_descr, _) -> | Null_field_access (_, _, origin_descr, _) ->
origin_descr_get_strict tenv origin_descr origin_descr_get_strict tenv origin_descr
| Parameter_annotation_inconsistent (Annotations.Nullable, _, _, _, _, origin_descr) | Parameter_annotation_inconsistent (AnnotatedSignature.Nullable, _, _, _, _, origin_descr)
when report_on_method_arguments -> when report_on_method_arguments ->
origin_descr_get_strict tenv origin_descr origin_descr_get_strict tenv origin_descr
| _ -> None | _ -> None
@ -296,13 +296,13 @@ let report_error_now tenv
origin_loc origin_loc
| Field_annotation_inconsistent (ann, fn, (origin_description, origin_loc, _)) -> | Field_annotation_inconsistent (ann, fn, (origin_description, origin_loc, _)) ->
let kind_s, description = match ann with let kind_s, description = match ann with
| Annotations.Nullable -> | AnnotatedSignature.Nullable ->
"ERADICATE_FIELD_NOT_NULLABLE", "ERADICATE_FIELD_NOT_NULLABLE",
P.sprintf P.sprintf
"Field `%s` can be null but is not declared `@Nullable`. %s" "Field `%s` can be null but is not declared `@Nullable`. %s"
(Ident.fieldname_to_simplified_string fn) (Ident.fieldname_to_simplified_string fn)
origin_description origin_description
| Annotations.Present -> | AnnotatedSignature.Present ->
"ERADICATE_FIELD_VALUE_ABSENT", "ERADICATE_FIELD_VALUE_ABSENT",
P.sprintf P.sprintf
"Field `%s` is assigned a possibly absent value but is declared `@Present`. %s" "Field `%s` is assigned a possibly absent value but is declared `@Present`. %s"
@ -348,14 +348,14 @@ let report_error_now tenv
origin_loc origin_loc
| Call_receiver_annotation_inconsistent (ann, s_opt, pn, (origin_description, origin_loc, _)) -> | Call_receiver_annotation_inconsistent (ann, s_opt, pn, (origin_description, origin_loc, _)) ->
let kind_s, description = match ann with let kind_s, description = match ann with
| Annotations.Nullable -> | AnnotatedSignature.Nullable ->
"ERADICATE_NULL_METHOD_CALL", "ERADICATE_NULL_METHOD_CALL",
P.sprintf P.sprintf
"The value of `%s` in the call to `%s` could be null. %s" "The value of `%s` in the call to `%s` could be null. %s"
(Option.value s_opt ~default:"") (Option.value s_opt ~default:"")
(Procname.to_simplified_string pn) (Procname.to_simplified_string pn)
origin_description origin_description
| Annotations.Present -> | AnnotatedSignature.Present ->
"ERADICATE_VALUE_NOT_PRESENT", "ERADICATE_VALUE_NOT_PRESENT",
P.sprintf P.sprintf
"The value of `%s` in the call to `%s` is not @Present. %s" "The value of `%s` in the call to `%s` is not @Present. %s"
@ -370,7 +370,7 @@ let report_error_now tenv
origin_loc origin_loc
| Parameter_annotation_inconsistent (ann, s, n, pn, _, (origin_desc, origin_loc, _)) -> | Parameter_annotation_inconsistent (ann, s, n, pn, _, (origin_desc, origin_loc, _)) ->
let kind_s, description = match ann with let kind_s, description = match ann with
| Annotations.Nullable -> | AnnotatedSignature.Nullable ->
"ERADICATE_PARAMETER_NOT_NULLABLE", "ERADICATE_PARAMETER_NOT_NULLABLE",
P.sprintf P.sprintf
"`%s` needs a non-null value in parameter %d but argument `%s` can be null. %s" "`%s` needs a non-null value in parameter %d but argument `%s` can be null. %s"
@ -378,7 +378,7 @@ let report_error_now tenv
n n
s s
origin_desc origin_desc
| Annotations.Present -> | AnnotatedSignature.Present ->
"ERADICATE_PARAMETER_VALUE_ABSENT", "ERADICATE_PARAMETER_VALUE_ABSENT",
P.sprintf P.sprintf
"`%s` needs a present value in parameter %d but argument `%s` can be absent. %s" "`%s` needs a present value in parameter %d but argument `%s` can be absent. %s"
@ -394,13 +394,13 @@ let report_error_now tenv
origin_loc origin_loc
| Return_annotation_inconsistent (ann, pn, (origin_description, origin_loc, _)) -> | Return_annotation_inconsistent (ann, pn, (origin_description, origin_loc, _)) ->
let kind_s, description = match ann with let kind_s, description = match ann with
| Annotations.Nullable -> | AnnotatedSignature.Nullable ->
"ERADICATE_RETURN_NOT_NULLABLE", "ERADICATE_RETURN_NOT_NULLABLE",
P.sprintf P.sprintf
"Method `%s` may return null but it is not annotated with `@Nullable`. %s" "Method `%s` may return null but it is not annotated with `@Nullable`. %s"
(Procname.to_simplified_string pn) (Procname.to_simplified_string pn)
origin_description origin_description
| Annotations.Present -> | AnnotatedSignature.Present ->
"ERADICATE_RETURN_VALUE_NOT_PRESENT", "ERADICATE_RETURN_VALUE_NOT_PRESENT",
P.sprintf P.sprintf
"Method `%s` may return an absent value but it is annotated with `@Present`. %s" "Method `%s` may return an absent value but it is annotated with `@Present`. %s"

@ -30,17 +30,17 @@ module InstrRef : InstrRefT
module Strict : module Strict :
sig sig
val signature_get_strict : val signature_get_strict :
Tenv.t -> Annotations.annotated_signature -> Annot.t option Tenv.t -> AnnotatedSignature.t -> Annot.t option
end (* Strict *) end (* Strict *)
type origin_descr = type origin_descr =
string * string *
Location.t option * Location.t option *
Annotations.annotated_signature option (* callee signature *) AnnotatedSignature.t option (* callee signature *)
type parameter_not_nullable = type parameter_not_nullable =
Annotations.annotation * AnnotatedSignature.annotation *
string * (* description *) string * (* description *)
int * (* parameter number *) int * (* parameter number *)
Procname.t * Procname.t *
@ -54,13 +54,13 @@ type err_instance =
| Inconsistent_subclass_parameter_annotation of string * int * Procname.t * Procname.t | Inconsistent_subclass_parameter_annotation of string * int * Procname.t * Procname.t
| Field_not_initialized of Ident.fieldname * Procname.t | Field_not_initialized of Ident.fieldname * Procname.t
| Field_not_mutable of Ident.fieldname * origin_descr | Field_not_mutable of Ident.fieldname * origin_descr
| Field_annotation_inconsistent of Annotations.annotation * Ident.fieldname * origin_descr | Field_annotation_inconsistent of AnnotatedSignature.annotation * Ident.fieldname * origin_descr
| Field_over_annotated of Ident.fieldname * Procname.t | Field_over_annotated of Ident.fieldname * Procname.t
| Null_field_access of string option * Ident.fieldname * origin_descr * bool | Null_field_access of string option * Ident.fieldname * origin_descr * bool
| Call_receiver_annotation_inconsistent | Call_receiver_annotation_inconsistent
of Annotations.annotation * string option * Procname.t * origin_descr of AnnotatedSignature.annotation * string option * Procname.t * origin_descr
| Parameter_annotation_inconsistent of parameter_not_nullable | Parameter_annotation_inconsistent of parameter_not_nullable
| Return_annotation_inconsistent of Annotations.annotation * Procname.t * origin_descr | Return_annotation_inconsistent of AnnotatedSignature.annotation * Procname.t * origin_descr
| Return_over_annotated of Procname.t | Return_over_annotated of Procname.t

@ -20,7 +20,7 @@ type proc_origin =
{ {
pname : Procname.t; pname : Procname.t;
loc: Location.t; loc: Location.t;
annotated_signature : Annotations.annotated_signature; annotated_signature : AnnotatedSignature.t;
is_library : bool; is_library : bool;
} [@@deriving compare] } [@@deriving compare]

@ -14,7 +14,7 @@ type proc_origin =
{ {
pname : Procname.t; pname : Procname.t;
loc: Location.t; loc: Location.t;
annotated_signature : Annotations.annotated_signature; annotated_signature : AnnotatedSignature.t;
is_library : bool; is_library : bool;
} [@@deriving compare] } [@@deriving compare]

Loading…
Cancel
Save