[C Frontend] Always add class prefix to a field name

Summary:
In objC we already prefix field names with classes.
It's better to make it consistent since it'll allow
us to share more code between C++ and objC
master
Andrzej Kotulski 9 years ago
parent 2a0cca5cc7
commit b328ee1509

@ -16,9 +16,6 @@ open Clang_ast_t
module L = Logging module L = Logging
let mk_class_field_name class_name field_name =
Ident.create_fieldname (Mangled.mangled field_name (class_name^"_"^field_name)) 0
let rec get_fields_super_classes tenv super_class = let rec get_fields_super_classes tenv super_class =
Printing.log_out " ... Getting fields of superclass '%s'\n" (Sil.typename_to_string super_class); Printing.log_out " ... Getting fields of superclass '%s'\n" (Sil.typename_to_string super_class);
match Sil.tenv_lookup tenv super_class with match Sil.tenv_lookup tenv super_class with

@ -14,5 +14,3 @@ val get_fields : Sil.tenv -> CContext.curr_class -> Clang_ast_t.decl list ->
val fields_superclass : Sil.tenv -> Clang_ast_t.obj_c_interface_decl_info -> val fields_superclass : Sil.tenv -> Clang_ast_t.obj_c_interface_decl_info ->
(Ident.fieldname * Sil.typ * Sil.item_annotation) list (Ident.fieldname * Sil.typ * Sil.item_annotation) list
val mk_class_field_name : string -> string -> Ident.fieldname

@ -369,6 +369,9 @@ struct
let replicate n el = list_map (fun i -> el) (list_range 0 (n -1)) let replicate n el = list_map (fun i -> el) (list_range 0 (n -1))
let mk_class_field_name class_name field_name =
Ident.create_fieldname (Mangled.mangled field_name (class_name^"_"^field_name)) 0
end end

@ -112,4 +112,7 @@ sig
val replicate: int -> 'a -> 'a list val replicate: int -> 'a -> 'a list
val mk_class_field_name : string -> string -> Ident.fieldname
end end

@ -75,7 +75,7 @@ struct
let procdesc = trans_state.context.procdesc in let procdesc = trans_state.context.procdesc in
let procname = Cfg.Procdesc.get_proc_name procdesc in let procname = Cfg.Procdesc.get_proc_name procdesc in
let mk_field_from_captured_var (vname, typ, b) = let mk_field_from_captured_var (vname, typ, b) =
let fname = CField_decl.mk_class_field_name block_name (Mangled.to_string vname) in let fname = General_utils.mk_class_field_name block_name (Mangled.to_string vname) in
let item_annot = Sil.item_annotation_empty in let item_annot = Sil.item_annotation_empty in
fname, typ, item_annot in fname, typ, item_annot in
let fields = list_map mk_field_from_captured_var captured_vars in let fields = list_map mk_field_from_captured_var captured_vars in

@ -179,24 +179,24 @@ and do_typedef_declaration tenv namespace decl_info name opt_type typedef_decl_i
(Sil.typename_to_string typename); (Sil.typename_to_string typename);
Sil.tenv_add tenv typename typ Sil.tenv_add tenv typename typ
and get_struct_fields tenv namespace decl_list = and get_struct_fields tenv record_name namespace decl_list =
match decl_list with match decl_list with
| [] -> [] | [] -> []
| FieldDecl(decl_info, name_info, qual_type, field_decl_info):: decl_list' -> | FieldDecl(decl_info, name_info, qual_type, field_decl_info):: decl_list' ->
let name = name_info.Clang_ast_t.ni_name in let field_name = name_info.Clang_ast_t.ni_name in
Printing.log_out " ...Defining field '%s'.\n" name; Printing.log_out " ...Defining field '%s'.\n" field_name;
let id = Ident.create_fieldname (Mangled.from_string name) 0 in let id = mk_class_field_name record_name field_name in
let typ = qual_type_to_sil_type tenv qual_type in let typ = qual_type_to_sil_type tenv qual_type in
let annotation_items = [] in (* For the moment we don't use them*) let annotation_items = [] in (* For the moment we don't use them*)
(id, typ, annotation_items):: get_struct_fields tenv namespace decl_list' (id, typ, annotation_items):: get_struct_fields tenv record_name namespace decl_list'
| CXXRecordDecl (decl_info, name, opt_type, decl_list, decl_context_info, record_decl_info) | CXXRecordDecl (decl_info, name, opt_type, decl_list, decl_context_info, record_decl_info)
:: decl_list' :: decl_list'
(* C++/C Records treated in the same way*) (* C++/C Records treated in the same way*)
| RecordDecl (decl_info, name, opt_type, decl_list, decl_context_info, record_decl_info) | RecordDecl (decl_info, name, opt_type, decl_list, decl_context_info, record_decl_info)
:: decl_list'-> :: decl_list'->
do_record_declaration tenv namespace decl_info name.Clang_ast_t.ni_name opt_type decl_list decl_context_info record_decl_info; do_record_declaration tenv namespace decl_info name.Clang_ast_t.ni_name opt_type decl_list decl_context_info record_decl_info;
get_struct_fields tenv namespace decl_list' get_struct_fields tenv record_name namespace decl_list'
| _ :: decl_list' -> get_struct_fields tenv namespace decl_list' | _ :: decl_list' -> get_struct_fields tenv record_name namespace decl_list'
and do_record_declaration tenv namespace decl_info name opt_type decl_list decl_context_info record_decl_info = and do_record_declaration tenv namespace decl_info name opt_type decl_list decl_context_info record_decl_info =
Printing.log_out "ADDING: RecordDecl for '%s'" name; Printing.log_out "ADDING: RecordDecl for '%s'" name;
@ -207,12 +207,18 @@ and do_record_declaration tenv namespace decl_info name opt_type decl_list decl_
let typ = expand_structured_type tenv typ in let typ = expand_structured_type tenv typ in
add_struct_to_tenv tenv typ add_struct_to_tenv tenv typ
(* We need to take the name out of the type as the struct can be anonymous*)
and get_record_name opt_type = match opt_type with
| `Type n' -> CTypes.cut_struct_union n'
| `NoType -> assert false
(* For a record declaration it returns/constructs the type *) (* For a record declaration it returns/constructs the type *)
and get_declaration_type tenv namespace decl_info n opt_type decl_list decl_context_info record_decl_info = and get_declaration_type tenv namespace decl_info n opt_type decl_list decl_context_info record_decl_info =
let ns_suffix = Ast_utils.namespace_to_string namespace in let ns_suffix = Ast_utils.namespace_to_string namespace in
let n = ns_suffix^n in let n = ns_suffix^n in
let name_str = get_record_name opt_type in
Printing.log_out "Record Declaration '%s' defined as struct\n" n; Printing.log_out "Record Declaration '%s' defined as struct\n" n;
let non_static_fields = get_struct_fields tenv namespace decl_list in let non_static_fields = get_struct_fields tenv name_str namespace decl_list in
let non_static_fields = if CTrans_models.is_objc_memory_model_controlled n then 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 append_no_duplicates_fields [Sil.objc_ref_counter_field] non_static_fields
else non_static_fields in else non_static_fields in
@ -224,9 +230,7 @@ and get_declaration_type tenv namespace decl_info n opt_type decl_list decl_cont
let csu = (match typ with let csu = (match typ with
| Sil.Tvar (Sil.TN_csu (csu, _)) -> csu | Sil.Tvar (Sil.TN_csu (csu, _)) -> csu
| _ -> Sil.Struct) in | _ -> Sil.Struct) in
let name = (match opt_type with (* We need to take the name out of the type as the struct can be anonymous*) let name = Some (Mangled.from_string name_str) in
| `Type n' -> Some (Mangled.from_string (CTypes.cut_struct_union n'))
| `NoType -> assert false) in
let superclass_list = [] in (* No super class for structs *) let superclass_list = [] in (* No super class for structs *)
let methods_list = [] in (* No methods list for structs *) let methods_list = [] in (* No methods list for structs *)
let item_annotation = Sil.item_annotation_empty in (* No annotations for struts *) let item_annotation = Sil.item_annotation_empty in (* No annotations for struts *)

@ -248,13 +248,13 @@ let rec find_field tenv nfield str searched_late_defined =
match str with match str with
| Some Sil.Tstruct (sf, nsf, Sil.Struct, Some cname, _, _, _) | Some Sil.Tstruct (sf, nsf, Sil.Struct, Some cname, _, _, _)
| Some Sil.Tstruct (sf, nsf, Sil.Union, Some cname, _, _, _) -> | Some Sil.Tstruct (sf, nsf, Sil.Union, Some cname, _, _, _) ->
(let name_field = Ident.create_fieldname (Mangled.from_string nfield) 0 in (let name_field = General_utils.mk_class_field_name (Mangled.to_string cname) nfield in
try try
Some (list_find (fun (fn, _, _) -> Sil.fld_equal fn name_field) (sf@nsf)) Some (list_find (fun (fn, _, _) -> Sil.fld_equal fn name_field) (sf@nsf))
with Not_found -> with Not_found ->
print_error name_field (sf@nsf); None) print_error name_field (sf@nsf); None)
| Some Sil.Tstruct (sf, nsf, Sil.Class, Some cname, super, _, _) -> | Some Sil.Tstruct (sf, nsf, Sil.Class, Some cname, super, _, _) ->
(let name_field = CField_decl.mk_class_field_name (Mangled.to_string cname) nfield in (let name_field = General_utils.mk_class_field_name (Mangled.to_string cname) nfield in
try try
Some (list_find (fun (fn, _, _) -> Sil.fld_equal fn name_field) (sf@nsf)) Some (list_find (fun (fn, _, _) -> Sil.fld_equal fn name_field) (sf@nsf))
with Not_found -> with Not_found ->

@ -0,0 +1,10 @@
struct X {
int a;
int b;
};
void test() {
X x;
x.a = 10;
x.b = 20;
}

@ -0,0 +1,10 @@
struct X {
int a;
int b;
};
void test() {
struct X x;
x.a = 10;
x.b = 20;
}

@ -0,0 +1,17 @@
digraph iCFG {
4 [label="4: BinaryOperatorStmt: Assign \n *&x.a:int =10 [line 8]\n " shape="box"]
4 -> 3 ;
3 [label="3: BinaryOperatorStmt: Assign \n *&x.b:int =20 [line 9]\n APPLY_ABSTRACTION; [line 9]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit test \n " color=yellow style=filled]
1 [label="1: Start test\nFormals: \nLocals: x:struct X \n DECLARE_LOCALS(&return,&x); [line 6]\n NULLIFY(&x,false); [line 6]\n " color=yellow style=filled]
1 -> 4 ;
}

@ -0,0 +1,21 @@
struct X_struct {
int a;
int b;
};
class X_class {
public:
int a;
int b;
};
void test() {
// use pointers until c++ constructors are translated
X_struct *xs;
xs->a = 10;
xs->b = 20;
X_class *xc;
xc->a = 10;
xc->b = 20;
}

@ -0,0 +1,25 @@
digraph iCFG {
6 [label="6: BinaryOperatorStmt: Assign \n n$3=*&xs:struct X_struct * [line 15]\n *n$3.a:int =10 [line 15]\n REMOVE_TEMPS(n$3); [line 15]\n " shape="box"]
6 -> 5 ;
5 [label="5: BinaryOperatorStmt: Assign \n n$2=*&xs:struct X_struct * [line 16]\n *n$2.b:int =20 [line 16]\n REMOVE_TEMPS(n$2); [line 16]\n NULLIFY(&xs,false); [line 16]\n " shape="box"]
5 -> 4 ;
4 [label="4: BinaryOperatorStmt: Assign \n n$1=*&xc:class X_class * [line 19]\n *n$1.a:int =10 [line 19]\n REMOVE_TEMPS(n$1); [line 19]\n " shape="box"]
4 -> 3 ;
3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&xc:class X_class * [line 20]\n *n$0.b:int =20 [line 20]\n REMOVE_TEMPS(n$0); [line 20]\n NULLIFY(&xc,false); [line 20]\n APPLY_ABSTRACTION; [line 20]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit test \n " color=yellow style=filled]
1 [label="1: Start test\nFormals: \nLocals: xs:struct X_struct * xc:class X_class * \n DECLARE_LOCALS(&return,&xs,&xc); [line 12]\n " color=yellow style=filled]
1 -> 6 ;
}

@ -0,0 +1,49 @@
/*
* Copyright (c) 2013 - 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.
*/
package frontend.c;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.DotFilesEqual.dotFileEqualTo;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferRunner;
public class TypesTest {
@Rule
public DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder();
@Test
public void whenCaptureRunStructThenDotFilesAreTheSame()
throws InterruptedException, IOException, InferException {
String switch_src =
"infer/tests/codetoanalyze/c/frontend/types/struct.c";
String switch_dotty =
"infer/tests/codetoanalyze/c/frontend/types/struct.dot";
ImmutableList<String> inferCmd =
InferRunner.createCInferCommandFrontend(folder, switch_src);
File newDotFile = InferRunner.runInferFrontend(inferCmd);
assertThat(
"In the capture of " + switch_src +
" the dotty files should be the same.",
newDotFile, dotFileEqualTo(switch_dotty));
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2013 - 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.
*/
package frontend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.DotFilesEqual.dotFileEqualTo;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferRunner;
public class ClassTest {
@Rule
public DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder();
@Test
public void whenCaptureRunCommaThenDotFilesAreTheSame()
throws InterruptedException, IOException, InferException {
String literal_src =
"infer/tests/codetoanalyze/cpp/frontend/types/struct.cpp";
String literal_dotty =
"infer/tests/codetoanalyze/cpp/frontend/types/struct.dot";
ImmutableList<String> inferCmd =
InferRunner.createCPPInferCommandFrontend(
folder,
literal_src);
File newDotFile = InferRunner.runInferFrontend(inferCmd);
assertThat(
"In the capture of " + literal_src +
" the dotty files should be the same.",
newDotFile, dotFileEqualTo(literal_dotty));
}
}
Loading…
Cancel
Save