From ca9ce581502ce84d433e94260397e95852331f12 Mon Sep 17 00:00:00 2001 From: Andrzej Kotulski Date: Fri, 25 Nov 2016 06:08:46 -0800 Subject: [PATCH] [reactive capture] reliably load proc attributes only for defined procedures Summary: introduce `AttributesTable.load_defined_attributes` which will return proc attributes only if the procedure is defined. In order to not mess up with existing caching, create another hashmap to store those procdescs. We need to do that because with reactive capture we no longer can assume that all proc attributes are final before analysis starts Reviewed By: jberdine Differential Revision: D4231575 fbshipit-source-id: e795bcb --- infer/src/IR/AttributesTable.re | 35 +++++++++++++++++++++++++------- infer/src/IR/AttributesTable.rei | 4 ++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/infer/src/IR/AttributesTable.re b/infer/src/IR/AttributesTable.re index b251ab121..35a7e7027 100644 --- a/infer/src/IR/AttributesTable.re +++ b/infer/src/IR/AttributesTable.re @@ -42,12 +42,16 @@ let res_dir_attr_filename defined::defined pname => { /* Load the proc attribute for the defined filename if it exists, otherwise try to load the declared filename. */ -let load_defined_first proc_name => { - let attributes_file defined => Multilinks.resolve ( +let load_attr defined_only::defined_only proc_name => { + let attributes_file defined::defined proc_name => Multilinks.resolve ( res_dir_attr_filename defined::defined proc_name ); - let attr = Serialization.from_file serializer (attributes_file true); - attr != None ? attr : Serialization.from_file serializer (attributes_file false) + let attr = Serialization.from_file serializer (attributes_file defined::true proc_name); + if (attr == None && defined_only == false) { + Serialization.from_file serializer (attributes_file defined::false proc_name) + } else { + attr + } }; /* Write a proc attributes to file. @@ -68,7 +72,7 @@ let write_and_delete proc_name (proc_attributes: ProcAttributes.t) => { let store_attributes (proc_attributes: ProcAttributes.t) => { let proc_name = proc_attributes.proc_name; let should_write = - switch (load_defined_first proc_name) { + switch (load_attr defined_only::false proc_name) { | None => true | Some proc_attributes_on_disk => let higher_rank_than_on_disk () => @@ -86,12 +90,29 @@ let store_attributes (proc_attributes: ProcAttributes.t) => { let attr_tbl = Procname.Hash.create 16; +let defined_attr_tbl = Procname.Hash.create 16; + let load_attributes proc_name => try (Procname.Hash.find attr_tbl proc_name) { | Not_found => - let proc_attributes = load_defined_first proc_name; + let proc_attributes = load_attr defined_only::false proc_name; + switch proc_attributes { + | Some attrs => + Procname.Hash.add attr_tbl proc_name proc_attributes; + if (attrs.is_defined == true) { + Procname.Hash.add defined_attr_tbl proc_name proc_attributes + } + | None => () + }; + proc_attributes + }; + +let load_defined_attributes proc_name => + try (Procname.Hash.find defined_attr_tbl proc_name) { + | Not_found => + let proc_attributes = load_attr defined_only::true proc_name; if (proc_attributes != None) { - Procname.Hash.add attr_tbl proc_name proc_attributes + Procname.Hash.add defined_attr_tbl proc_name proc_attributes }; proc_attributes }; diff --git a/infer/src/IR/AttributesTable.rei b/infer/src/IR/AttributesTable.rei index 50515c6e9..371ca4288 100644 --- a/infer/src/IR/AttributesTable.rei +++ b/infer/src/IR/AttributesTable.rei @@ -19,6 +19,10 @@ let store_attributes: ProcAttributes.t => unit; let load_attributes: Procname.t => option ProcAttributes.t; +/** Load attrubutes for the procedure but only if is_defined is true */ +let load_defined_attributes: Procname.t => option ProcAttributes.t; + + /** Given the name of an ObjC class, extract the type from the tenv where the class was defined. We do this by adding a method that is unique to each class, and then finding the tenv that corresponds to the class definition. */