[clang] Sorting the fields in structs and classes. Was needed in the backend and forgotten.

Summary:
@public
Sorting the fields in structs and classes. Was needed in the backend and forgotten.
Fixes the github issue https://github.com/facebook/infer/issues/90.

Test Plan: Added a new test that shows that we now get a spec for the example from the github issue.
master
Dulma Rodriguez 10 years ago
parent 843e600bb1
commit 510fc4ed25

@ -28,7 +28,6 @@ struct
then Format.fprintf else Format.ifprintf in
pp Format.std_formatter fmt
let print_tenv tenv =
Sil.tenv_iter (fun typname typ ->
match typname with
@ -292,6 +291,11 @@ struct
| _, _, _ -> false in
append_no_duplicates field_eq list1 list2
let sort_fields fields =
let compare (name1, _, _) (name2, _, _) =
Ident.fieldname_compare name1 name2 in
list_sort compare fields
let rec collect_list_tuples l (a, a1, b, c, d) =
match l with
| [] -> (a, a1, b, c, d)

@ -79,6 +79,8 @@ sig
val append_no_duplicated_pvars : (Sil.exp * Sil.typ) list -> (Sil.exp * Sil.typ) list -> (Sil.exp * Sil.typ) list
val sort_fields : (Ident.fieldname * Sil.typ * Sil.item_annotation) list -> (Ident.fieldname * Sil.typ * Sil.item_annotation) list
val collect_list_tuples : ('a list * 'b list * 'c list * 'd list * 'e list) list ->
'a list * 'b list * 'c list * 'd list * 'e list -> 'a list * 'b list * 'c list * 'd list * 'e list

@ -75,6 +75,7 @@ struct
let item_annot = Sil.item_annotation_empty in
fname, typ, item_annot in
let fields = list_map mk_field_from_captured_var captured_vars in
let fields = CFrontend_utils.General_utils.sort_fields fields in
Printing.log_out "Block %s field:\n" block_name;
list_iter (fun (fn, ft, _) ->
Printing.log_out "-----> field: '%s'\n" (Ident.fieldname_to_string fn)) fields;

@ -211,6 +211,7 @@ and get_declaration_type tenv namespace decl_info n opt_type decl_list decl_cont
let non_static_fields = if CTrans_models.is_objc_memory_model_controlled n then
append_no_duplicates_fields [Sil.objc_ref_counter_field] non_static_fields
else non_static_fields in
let non_static_fields = CFrontend_utils.General_utils.sort_fields non_static_fields in
let static_fields = [] in (* Warning for the moment we do not treat static field. *)
let typ = (match opt_type with
| `Type s -> qual_type_to_sil_type_no_expansions tenv (Ast_expressions.create_qual_type s)

@ -48,6 +48,7 @@ let process_category tenv name class_name decl_list =
match Sil.tenv_lookup tenv class_tn_name with
| Some Sil.Tstruct (intf_fields, _, _, _, superclass, intf_methods, annotation) ->
let new_fields = General_utils.append_no_duplicates_fields fields intf_fields in
let new_fields = CFrontend_utils.General_utils.sort_fields new_fields in
let new_methods = General_utils.append_no_duplicates_methods methods intf_methods in
let class_type_info =
Sil.Tstruct (

@ -111,6 +111,7 @@ let add_class_to_tenv tenv class_name decl_list obj_c_interface_decl_info =
let fields = append_no_duplicates_fields fields fields_sc in
(* We add the special hidden counter_field for implementing reference counting *)
let fields = append_no_duplicates_fields [Sil.objc_ref_counter_field] fields in
let fields = CFrontend_utils.General_utils.sort_fields fields in
Printing.log_out "Class %s field:\n" class_name;
list_iter (fun (fn, ft, _) ->
Printing.log_out "-----> field: '%s'\n" (Ident.fieldname_to_string fn)) fields;
@ -152,6 +153,7 @@ let add_missing_fields tenv class_name decl_list idi =
" ---> Extra non-static field: '%s'\n" (Ident.fieldname_to_string fn))
extra_fields;
let new_fields = append_no_duplicates_fields extra_fields intf_fields in
let new_fields = CFrontend_utils.General_utils.sort_fields new_fields in
let class_type_info =
Sil.Tstruct (
new_fields, [], Sil.Class, Some mang_name, superclass, methods, annotation

@ -7,6 +7,7 @@ all:
make -C null_dereference
make -C resource_leaks
make -C memory_leaks
make -C lists
clean:
make -C arithmetic clean
@ -16,4 +17,5 @@ clean:
make -C null_dereference clean
make -C resource_leaks clean
make -C memory_leaks
make -C lists

@ -0,0 +1,12 @@
SOURCES = $(shell ls *.c)
OBJECTS = $(SOURCES:.c=.o)
all: clean $(OBJECTS)
echo $(OBJECTS)
.c.o:
${CC} -c $<
clean:
rm -rf $(OBJECTS)

@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 - Facebook.
* All rights reserved.
*/
struct l2 {
int b;
struct l2 *a;
};
int add2(struct l2 *l) {
int r = 0;
for (; l; l = l->a) {
r += l->b;
}
return r;
}
/* Divide by zero error shows that we get a spec for add2 */
int main() {
int res = add2(0);
return 5/res;
}

@ -1,5 +1,5 @@
digraph iCFG {
14 [label="14: InitListExp \n *&e.ssn:int =12 [line 37]\n *&e.salary:float =3000.500000 [line 37]\n *&e.doj.date:int =12 [line 37]\n *&e.doj.month:int =12 [line 37]\n *&e.doj.year:int =2010 [line 37]\n " shape="box"]
14 [label="14: InitListExp \n *&e.doj.date:int =12 [line 37]\n *&e.doj.month:int =3000.500000 [line 37]\n *&e.doj.year:int =12 [line 37]\n *&e.salary:float =12 [line 37]\n *&e.ssn:int =2010 [line 37]\n " shape="box"]
14 -> 13 ;

@ -26,7 +26,7 @@ digraph iCFG {
19 -> 18 ;
18 [label="18: BinaryOperatorStmt: Assign \n DECLARE_LOCALS(&__objc_anonymous_block___objc_anonymous_block_main1______2______3); [line 21]\n n$22=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block___objc_anonymous_block_main1______2______3 ):class __objc_anonymous_block___objc_anonymous_block_main1______2______3 *) [line 21]\n *&__objc_anonymous_block___objc_anonymous_block_main1______2______3:class __objc_anonymous_block___objc_anonymous_block_main1______2______3 =n$22 [line 21]\n n$23=*&x:int [line 21]\n n$24=*&bla:int [line 21]\n *n$22.x:int =n$23 [line 21]\n *n$22.bla:int =n$24 [line 21]\n n$16=*&x:int [line 21]\n n$17=*&bla:int [line 21]\n *&addblock2:_fn_ (*)=(_fun___objc_anonymous_block___objc_anonymous_block_main1______2______3,n$16,n$17) [line 21]\n REMOVE_TEMPS(n$22,n$23,n$24,n$16,n$17); [line 21]\n " shape="box"]
18 [label="18: BinaryOperatorStmt: Assign \n DECLARE_LOCALS(&__objc_anonymous_block___objc_anonymous_block_main1______2______3); [line 21]\n n$22=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block___objc_anonymous_block_main1______2______3 ):class __objc_anonymous_block___objc_anonymous_block_main1______2______3 *) [line 21]\n *&__objc_anonymous_block___objc_anonymous_block_main1______2______3:class __objc_anonymous_block___objc_anonymous_block_main1______2______3 =n$22 [line 21]\n n$23=*&x:int [line 21]\n n$24=*&bla:int [line 21]\n *n$22.bla:int =n$23 [line 21]\n *n$22.x:int =n$24 [line 21]\n n$16=*&x:int [line 21]\n n$17=*&bla:int [line 21]\n *&addblock2:_fn_ (*)=(_fun___objc_anonymous_block___objc_anonymous_block_main1______2______3,n$16,n$17) [line 21]\n REMOVE_TEMPS(n$22,n$23,n$24,n$16,n$17); [line 21]\n " shape="box"]
18 -> 14 ;

@ -0,0 +1,48 @@
/*
* Copyright (c) 2013- Facebook.
* All rights reserved.
*/
package endtoend.c;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import utils.InferException;
import utils.InferResults;
public class ListsTest {
public static final String SOURCE_FILE = "lists/lists.c";
public static final String DIVIDE_BY_ZERO = "DIVIDE_BY_ZERO";
private static InferResults inferResults;
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferResults = InferResults.loadCInferResults(DivideByZeroTest.class, SOURCE_FILE);
}
@Test
public void whenInferRunsOnDivideByZeroThenDivideByZeroIsFound()
throws InterruptedException, IOException, InferException {
String[] procedures = {"main"};
assertThat(
"Results should contain divide by zero error",
inferResults,
containsExactly(
DIVIDE_BY_ZERO,
SOURCE_FILE,
procedures
)
);
}
}
Loading…
Cancel
Save