From e8949d16e4bf2372de1bd93f5d0556b366595ac6 Mon Sep 17 00:00:00 2001 From: Andrzej Kotulski Date: Mon, 28 Sep 2015 09:57:13 -0100 Subject: [PATCH] [Frontend][C++] Use Sil.class for C++ class/struct/union types Summary: frontend and backend assume that Sil.Struct doesn't have methods nor inheritance. In order to plug C++ classes we probably need them to be Sil.Class --- facebook-clang-plugins | 2 +- infer/src/clang/cMethod_trans.ml | 2 +- infer/src/clang/cTypes_decl.ml | 24 ++++++++++------- .../cpp/frontend/types/inheritance.dot | 6 ++--- .../cpp/frontend/types/methods.dot | 26 +++++++++---------- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/facebook-clang-plugins b/facebook-clang-plugins index c5d9c5894..7448f0c1a 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit c5d9c58940ccb7e7ae3113af9fb6c84e895e34ac +Subproject commit 7448f0c1a80b1a6f8a2e826c3acafc3df7f9621e diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 6a16a6494..c116af0a3 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -45,7 +45,7 @@ let get_class_param function_method_decl_info = if (is_instance_method function_method_decl_info false) then match function_method_decl_info with | Cpp_Meth_decl_info (_, class_name, _) -> - let class_type = Ast_expressions.create_struct_type class_name in + let class_type = Ast_expressions.create_class_type class_name in [(CFrontend_config.this, class_type, None)] | ObjC_Meth_decl_info (_, class_name) -> let class_type = Ast_expressions.create_class_type class_name in diff --git a/infer/src/clang/cTypes_decl.ml b/infer/src/clang/cTypes_decl.ml index 734a812f9..acaa36840 100644 --- a/infer/src/clang/cTypes_decl.ml +++ b/infer/src/clang/cTypes_decl.ml @@ -78,20 +78,24 @@ let create_csu opt_type = | _ -> assert false (* We need to take the name out of the type as the struct can be anonymous*) -let get_record_name_csu opt_type name_info = - let name_str = name_info.Clang_ast_t.ni_name in +let get_record_name_csu decl = + let open Clang_ast_t in + let name_info, opt_type, should_be_class = match decl with + | RecordDecl (_, name_info, opt_type, _, _, _, _) -> name_info, opt_type, false + | CXXRecordDecl (_, name_info, opt_type, _, _, _, _, cxx_record_info) -> + (* we use Sil.Class for C++ because we expect Sil.Class csu from *) + (* types that have methods. And in C++ struct/class/union can have methods *) + name_info, opt_type, not cxx_record_info.xrdi_is_c_like + | _-> assert false in + let name_str = name_info.ni_name in let csu, type_name = create_csu opt_type in + let csu' = if should_be_class then Sil.Class else csu in let prefix = Ast_utils.get_qualifier_string name_info in let name = if (String.length name_str = 0) then prefix ^ type_name else prefix ^ name_str in - csu, name + csu', name -let get_record_name decl = - let name_info, opt_type = match decl with - | Clang_ast_t.RecordDecl (_, name_info, opt_type, _, _, _, _) - | Clang_ast_t.CXXRecordDecl (_, name_info, opt_type, _, _, _, _, _) -> name_info, opt_type - | _ -> assert false in - snd (get_record_name_csu opt_type name_info) +let get_record_name decl = snd (get_record_name_csu decl) let get_method_decls parent decl_list = let open Clang_ast_t in @@ -155,7 +159,7 @@ and get_declaration_type tenv namespace decl = match decl with | CXXRecordDecl (decl_info, name_info, opt_type, type_ptr, decl_list, _, record_decl_info, _) | RecordDecl (decl_info, name_info, opt_type, type_ptr, decl_list, _, record_decl_info) -> - let csu, name = get_record_name_csu opt_type name_info in + let csu, name = get_record_name_csu decl in let mangled_name = Mangled.from_string name in let sil_typename = Sil.Tvar (Sil.TN_csu (csu, mangled_name)) in (* temporarily saves the type name to avoid infinite loops in recursive types *) diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.dot b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.dot index dedcd2b2b..d0e7add41 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.dot @@ -49,7 +49,7 @@ digraph iCFG { 8 [label="8: Exit Sub_fun_redefine \n " color=yellow style=filled] -7 [label="7: Start Sub_fun_redefine\nFormals: this:struct Sub \nLocals: \n DECLARE_LOCALS(&return); [line 18]\n NULLIFY(&this,false); [line 18]\n " color=yellow style=filled] +7 [label="7: Start Sub_fun_redefine\nFormals: this:class Sub \nLocals: \n DECLARE_LOCALS(&return); [line 18]\n NULLIFY(&this,false); [line 18]\n " color=yellow style=filled] 7 -> 9 ; @@ -60,7 +60,7 @@ digraph iCFG { 5 [label="5: Exit Base_fun_redefine \n " color=yellow style=filled] -4 [label="4: Start Base_fun_redefine\nFormals: this:struct Base \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n NULLIFY(&this,false); [line 13]\n " color=yellow style=filled] +4 [label="4: Start Base_fun_redefine\nFormals: this:class Base \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n NULLIFY(&this,false); [line 13]\n " color=yellow style=filled] 4 -> 6 ; @@ -71,7 +71,7 @@ digraph iCFG { 2 [label="2: Exit Base_fun \n " color=yellow style=filled] -1 [label="1: Start Base_fun\nFormals: this:struct Base \nLocals: \n DECLARE_LOCALS(&return); [line 12]\n NULLIFY(&this,false); [line 12]\n " color=yellow style=filled] +1 [label="1: Start Base_fun\nFormals: this:class Base \nLocals: \n DECLARE_LOCALS(&return); [line 12]\n NULLIFY(&this,false); [line 12]\n " color=yellow style=filled] 1 -> 3 ; diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot b/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot index 9ee1390ec..d94032fc3 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot @@ -1,38 +1,38 @@ digraph iCFG { -29 [label="29: Call _fun_A_fun_default \n n$2=*&a_ptr:struct A * [line 59]\n n$3=_fun_A_fun_default(n$2:struct A ,1:int ,2:int ,20:int ) [line 59]\n REMOVE_TEMPS(n$2,n$3); [line 59]\n " shape="box"] +29 [label="29: Call _fun_A_fun_default \n n$2=*&a_ptr:class A * [line 59]\n n$3=_fun_A_fun_default(n$2:class A ,1:int ,2:int ,20:int ) [line 59]\n REMOVE_TEMPS(n$2,n$3); [line 59]\n " shape="box"] 29 -> 28 ; -28 [label="28: Call _fun_A_fun_default \n n$0=*&a_ptr:struct A * [line 60]\n n$1=_fun_A_fun_default(n$0:struct A ,1:int ,10:int ,20:int ) [line 60]\n REMOVE_TEMPS(n$0,n$1); [line 60]\n NULLIFY(&a_ptr,false); [line 60]\n APPLY_ABSTRACTION; [line 60]\n " shape="box"] +28 [label="28: Call _fun_A_fun_default \n n$0=*&a_ptr:class A * [line 60]\n n$1=_fun_A_fun_default(n$0:class A ,1:int ,10:int ,20:int ) [line 60]\n REMOVE_TEMPS(n$0,n$1); [line 60]\n NULLIFY(&a_ptr,false); [line 60]\n APPLY_ABSTRACTION; [line 60]\n " shape="box"] 28 -> 27 ; 27 [label="27: Exit call_method_with_default_parameters \n " color=yellow style=filled] -26 [label="26: Start call_method_with_default_parameters\nFormals: \nLocals: a_ptr:struct A * \n DECLARE_LOCALS(&return,&a_ptr); [line 57]\n " color=yellow style=filled] +26 [label="26: Start call_method_with_default_parameters\nFormals: \nLocals: a_ptr:class A * \n DECLARE_LOCALS(&return,&a_ptr); [line 57]\n " color=yellow style=filled] 26 -> 29 ; -25 [label="25: Call _fun_A_fun \n n$2=*&a_ptr:struct A * [line 53]\n n$3=_fun_A_fun(n$2:struct A ,10:int ,20:int ) [line 53]\n REMOVE_TEMPS(n$2,n$3); [line 53]\n " shape="box"] +25 [label="25: Call _fun_A_fun \n n$2=*&a_ptr:class A * [line 53]\n n$3=_fun_A_fun(n$2:class A ,10:int ,20:int ) [line 53]\n REMOVE_TEMPS(n$2,n$3); [line 53]\n " shape="box"] 25 -> 24 ; -24 [label="24: Call _fun_A_fun_default \n n$0=*&a_ptr:struct A * [line 54]\n n$1=_fun_A_fun_default(n$0:struct A ,1:int ,2:int ,3:int ) [line 54]\n REMOVE_TEMPS(n$0,n$1); [line 54]\n NULLIFY(&a_ptr,false); [line 54]\n APPLY_ABSTRACTION; [line 54]\n " shape="box"] +24 [label="24: Call _fun_A_fun_default \n n$0=*&a_ptr:class A * [line 54]\n n$1=_fun_A_fun_default(n$0:class A ,1:int ,2:int ,3:int ) [line 54]\n REMOVE_TEMPS(n$0,n$1); [line 54]\n NULLIFY(&a_ptr,false); [line 54]\n APPLY_ABSTRACTION; [line 54]\n " shape="box"] 24 -> 23 ; 23 [label="23: Exit call_method \n " color=yellow style=filled] -22 [label="22: Start call_method\nFormals: \nLocals: a_ptr:struct A * \n DECLARE_LOCALS(&return,&a_ptr); [line 46]\n " color=yellow style=filled] +22 [label="22: Start call_method\nFormals: \nLocals: a_ptr:class A * \n DECLARE_LOCALS(&return,&a_ptr); [line 46]\n " color=yellow style=filled] 22 -> 25 ; 21 [label="21: Exit A_add \n " color=yellow style=filled] -20 [label="20: Start A_add\nFormals: this:struct A other:struct A &\nLocals: \n DECLARE_LOCALS(&return); [line 41]\n NULLIFY(&other,false); [line 41]\n NULLIFY(&this,false); [line 41]\n " color=yellow style=filled] +20 [label="20: Start A_add\nFormals: this:class A other:class A &\nLocals: \n DECLARE_LOCALS(&return); [line 41]\n NULLIFY(&other,false); [line 41]\n NULLIFY(&this,false); [line 41]\n " color=yellow style=filled] 20 -> 21 ; @@ -43,7 +43,7 @@ digraph iCFG { 18 [label="18: Exit A::AIn_fun \n " color=yellow style=filled] -17 [label="17: Start A::AIn_fun\nFormals: this:struct A::AIn a:int b:int \nLocals: \n DECLARE_LOCALS(&return); [line 37]\n NULLIFY(&this,false); [line 37]\n " color=yellow style=filled] +17 [label="17: Start A::AIn_fun\nFormals: this:class A::AIn a:int b:int \nLocals: \n DECLARE_LOCALS(&return); [line 37]\n NULLIFY(&this,false); [line 37]\n " color=yellow style=filled] 17 -> 19 ; @@ -58,14 +58,14 @@ digraph iCFG { 14 [label="14: Exit A_fun \n " color=yellow style=filled] -13 [label="13: Start A_fun\nFormals: this:struct A a:int b:int \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 30]\n NULLIFY(&c,false); [line 30]\n NULLIFY(&this,false); [line 30]\n " color=yellow style=filled] +13 [label="13: Start A_fun\nFormals: this:class A a:int b:int \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 30]\n NULLIFY(&c,false); [line 30]\n NULLIFY(&this,false); [line 30]\n " color=yellow style=filled] 13 -> 16 ; 12 [label="12: Exit A_fun \n " color=yellow style=filled] -11 [label="11: Start A_fun\nFormals: this:struct A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n NULLIFY(&a,false); [line 25]\n NULLIFY(&b,false); [line 25]\n NULLIFY(&c,false); [line 25]\n NULLIFY(&this,false); [line 25]\n " color=yellow style=filled] +11 [label="11: Start A_fun\nFormals: this:class A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n NULLIFY(&a,false); [line 25]\n NULLIFY(&b,false); [line 25]\n NULLIFY(&c,false); [line 25]\n NULLIFY(&this,false); [line 25]\n " color=yellow style=filled] 11 -> 12 ; @@ -76,7 +76,7 @@ digraph iCFG { 9 [label="9: Exit A_fun_default \n " color=yellow style=filled] -8 [label="8: Start A_fun_default\nFormals: this:struct A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 20]\n NULLIFY(&this,false); [line 20]\n " color=yellow style=filled] +8 [label="8: Start A_fun_default\nFormals: this:class A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 20]\n NULLIFY(&this,false); [line 20]\n " color=yellow style=filled] 8 -> 10 ; @@ -91,7 +91,7 @@ digraph iCFG { 5 [label="5: Exit A_def_in \n " color=yellow style=filled] -4 [label="4: Start A_def_in\nFormals: this:struct A \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 17]\n NULLIFY(&c,false); [line 17]\n NULLIFY(&this,false); [line 17]\n " color=yellow style=filled] +4 [label="4: Start A_def_in\nFormals: this:class A \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 17]\n NULLIFY(&c,false); [line 17]\n NULLIFY(&this,false); [line 17]\n " color=yellow style=filled] 4 -> 7 ; @@ -102,7 +102,7 @@ digraph iCFG { 2 [label="2: Exit A::AIn_fun1 \n " color=yellow style=filled] -1 [label="1: Start A::AIn_fun1\nFormals: this:struct A::AIn \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n NULLIFY(&this,false); [line 13]\n " color=yellow style=filled] +1 [label="1: Start A::AIn_fun1\nFormals: this:class A::AIn \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n NULLIFY(&this,false); [line 13]\n " color=yellow style=filled] 1 -> 3 ;