Detecting if methods annotated with @PerformanceCritical transitively call methods annotated with @Expensive

Summary: public
Just works by running the analysis bottom-up and promoting any method as virtually annotated with `Expensive` whenever one of its callee is annotated with `Expensive`

Reviewed By: cristianoc

Differential Revision: D2635242

fb-gh-sync-id: 4401be6
master
jrm 9 years ago committed by facebook-github-bot-1
parent 8636aa1f70
commit 6b6b4d1949

@ -112,6 +112,11 @@ let verify_annotation = "com.facebook.infer.annotation.Verify"
let expensive = "Expensive"
let performance_critical = "PerformanceCritical"
let expensive_annotation = {
Sil.class_name = expensive;
Sil.parameters = []
}
let ia_is_nullable ia =
ia_ends_with ia nullable
@ -163,7 +168,6 @@ 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

@ -14,6 +14,8 @@ val suppressLint : string
val expensive : string
val performance_critical : string
val expensive_annotation : Sil.annotation
type annotation =
| Nullable
| Present

@ -33,10 +33,18 @@ let search_expensive_call checked_pnames expensive_callee (pname, _) =
end
let is_performance_critical attributes =
let check_attributes check attributes =
let annotated_signature = Annotations.get_annotated_signature attributes in
let ret_annotation, _ = annotated_signature.Annotations.ret in
Annotations.ia_is_performance_critical ret_annotation
check ret_annotation
let is_performance_critical attributes =
check_attributes Annotations.ia_is_performance_critical attributes
let is_expensive attributes =
check_attributes Annotations.ia_is_expensive attributes
let callback_performance_checker _ _ _ tenv pname pdesc : unit =
@ -58,4 +66,11 @@ let callback_performance_checker _ _ _ tenv pname pdesc : unit =
Annotations.expensive in
Checkers.ST.report_error
pname pdesc calls_expensive_method (Cfg.Procdesc.get_loc pdesc) description
| Some _ -> ()
| Some _ when not (is_expensive attributes) ->
let ret_annot, param_annot = attributes.ProcAttributes.method_annotation in
let updated_method_annot =
(Annotations.expensive_annotation, true) :: ret_annot, param_annot in
let updated_attributes =
{ attributes with ProcAttributes.method_annotation = updated_method_annot } in
AttributesTable.store_attributes updated_attributes
| Some _ -> () (* Nothing to do if method already annotated with @Expensive *)

@ -16,14 +16,30 @@ public class ExpensiveCallExample {
Object mObject;
void nonExpensiveMethod() {}
@Expensive
void expensiveMethod() {
mObject = new Object();
}
void methodWrapper() {
expensiveMethod();
}
@PerformanceCritical
void notCallingExpensiveMethod() {
nonExpensiveMethod();
}
@PerformanceCritical
void shouldReportExpensiveCallWarning() {
void directlyCallingExpensiveMethod() {
expensiveMethod();
}
@PerformanceCritical
void indirectlyCallingExpensiveMethod() {
methodWrapper();
}
}

@ -39,7 +39,8 @@ public class ExpensiveCallTest {
public void matchErrors()
throws IOException, InterruptedException, InferException {
String[] methods = {
"shouldReportExpensiveCallWarning",
"directlyCallingExpensiveMethod",
"indirectlyCallingExpensiveMethod"
};
assertThat(
"Results should contain " + CALLS_EXPENSIVE_METHOD,

Loading…
Cancel
Save