diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 1f226b890..404023657 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -182,9 +182,13 @@ let get_formal_parameters tenv ms = match pl with | [] -> [] | (name, raw_type, _):: pl' -> - let is_objc_self = name = CFrontend_config.self && - CMethod_signature.ms_get_lang ms = CFrontend_config.OBJC in - let tp = if is_objc_self && CMethod_signature.ms_is_instance ms then + let should_add_pointer name ms = + let is_objc_self = name = CFrontend_config.self && + CMethod_signature.ms_get_lang ms = CFrontend_config.OBJC in + let is_cxx_this = name = CFrontend_config.this && + CMethod_signature.ms_get_lang ms = CFrontend_config.CPP in + (is_objc_self && CMethod_signature.ms_is_instance ms) || is_cxx_this in + let tp = if should_add_pointer name ms then (Ast_expressions.create_pointer_type raw_type) else raw_type in let typ = CTypes_decl.type_ptr_to_sil_type tenv tp in diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 380e9840f..1765ac264 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -357,6 +357,23 @@ struct { empty_res_trans with exps = exps } ) + let cxxThisExpr_trans trans_state stmt_info expr_info = + let context = trans_state.context in + let pln = trans_state.parent_line_number in + let sil_loc = CLocation.get_sil_location stmt_info pln context in + let tp = expr_info.Clang_ast_t.ei_type_ptr in + let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in + let name = CFrontend_config.this in + let pvar = Sil.mk_pvar (Mangled.from_string name) procname in + let exp = Sil.Lvar pvar in + let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv tp in + let exps = [(exp, typ)] in + (* there is no cast operation in AST, but backend needs it *) + let cast_kind = `LValueToRValue in + let cast_ids, cast_inst, cast_exp = cast_operation context cast_kind exps + (* unused *) typ sil_loc (* is_objc_bridged *) false in + { empty_res_trans with ids = cast_ids; instrs = cast_inst; exps = [(cast_exp, typ)] } + let rec labelStmt_trans trans_state stmt_info stmt_list label_name = (* go ahead with the translation *) let res_trans = match stmt_list with @@ -1873,6 +1890,8 @@ struct | ObjCPropertyRefExpr(stmt_info, stmt_list, expr_info, property_ref_expr_info) -> objCPropertyRefExpr_trans trans_state stmt_info stmt_list + | CXXThisExpr(stmt_info, _, expr_info) -> cxxThisExpr_trans trans_state stmt_info expr_info + | OpaqueValueExpr(stmt_info, stmt_list, expr_info, opaque_value_expr_info) -> opaqueValueExpr_trans trans_state stmt_info opaque_value_expr_info diff --git a/infer/tests/codetoanalyze/cpp/frontend/keywords/self_parameter.dot b/infer/tests/codetoanalyze/cpp/frontend/keywords/self_parameter.dot index 75d46b07f..4caf8c0c3 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/keywords/self_parameter.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/keywords/self_parameter.dot @@ -28,7 +28,7 @@ digraph iCFG { 2 [label="2: Exit A_meth_with_self \n " color=yellow style=filled] -1 [label="1: Start A_meth_with_self\nFormals: this:class A self:int b:int \nLocals: \n DECLARE_LOCALS(&return); [line 12]\n NULLIFY(&this,false); [line 12]\n " color=yellow style=filled] +1 [label="1: Start A_meth_with_self\nFormals: this:class A * self:int b:int \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/methods/default_parameters.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/methods/default_parameters.cpp.dot index c44c8a155..d8393ce52 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/methods/default_parameters.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/methods/default_parameters.cpp.dot @@ -25,7 +25,7 @@ digraph iCFG { 2 [label="2: Exit A_fun_default \n " color=yellow style=filled] -1 [label="1: Start A_fun_default\nFormals: this:class A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n NULLIFY(&this,false); [line 13]\n " color=yellow style=filled] +1 [label="1: Start A_fun_default\nFormals: this:class A * a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n NULLIFY(&this,false); [line 13]\n " color=yellow style=filled] 1 -> 3 ; diff --git a/infer/tests/codetoanalyze/cpp/frontend/methods/dereference_this.cpp b/infer/tests/codetoanalyze/cpp/frontend/methods/dereference_this.cpp new file mode 100644 index 000000000..402c9cd48 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/methods/dereference_this.cpp @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2015 - 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. +*/ + +class A { +int field; +public: + void init(int val) { field = val; } + int method(); +}; + +int A::method() { + init(10); // call method on the object + return field; +} + +void test() { + A *a_ptr; + a_ptr->method(); +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/methods/dereference_this.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/methods/dereference_this.cpp.dot new file mode 100644 index 000000000..a0c0ac461 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/methods/dereference_this.cpp.dot @@ -0,0 +1,39 @@ +digraph iCFG { +10 [label="10: Call _fun_A_method \n n$0=*&a_ptr:class A * [line 24]\n n$1=_fun_A_method(n$0:class A ) [line 24]\n REMOVE_TEMPS(n$0,n$1); [line 24]\n NULLIFY(&a_ptr,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] + + + 10 -> 9 ; +9 [label="9: Exit test \n " color=yellow style=filled] + + +8 [label="8: Start test\nFormals: \nLocals: a_ptr:class A * \n DECLARE_LOCALS(&return,&a_ptr); [line 22]\n " color=yellow style=filled] + + + 8 -> 10 ; +7 [label="7: Call _fun_A_init \n n$2=*&this:class A * [line 18]\n _fun_A_init(n$2:class A ,10:int ) [line 18]\n REMOVE_TEMPS(n$2); [line 18]\n " shape="box"] + + + 7 -> 6 ; +6 [label="6: Return Stmt \n n$0=*&this:class A * [line 19]\n n$1=*n$0.field:int [line 19]\n *&return:int =n$1 [line 19]\n REMOVE_TEMPS(n$0,n$1); [line 19]\n NULLIFY(&this,false); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"] + + + 6 -> 5 ; +5 [label="5: Exit A_method \n " color=yellow style=filled] + + +4 [label="4: Start A_method\nFormals: this:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 17]\n " color=yellow style=filled] + + + 4 -> 7 ; +3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&this:class A * [line 13]\n n$1=*&val:int [line 13]\n *n$0.field:int =n$1 [line 13]\n REMOVE_TEMPS(n$0,n$1); [line 13]\n NULLIFY(&this,false); [line 13]\n NULLIFY(&val,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit A_init \n " color=yellow style=filled] + + +1 [label="1: Start A_init\nFormals: this:class A * val:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled] + + + 1 -> 3 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/methods/inline_method.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/methods/inline_method.cpp.dot index bb919a8fd..939d625c7 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/methods/inline_method.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/methods/inline_method.cpp.dot @@ -25,7 +25,7 @@ digraph iCFG { 5 [label="5: Exit A_fun \n " color=yellow style=filled] -4 [label="4: Start A_fun\nFormals: this:class A \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 16]\n NULLIFY(&c,false); [line 16]\n NULLIFY(&this,false); [line 16]\n " color=yellow style=filled] +4 [label="4: Start A_fun\nFormals: this:class A *\nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 16]\n NULLIFY(&c,false); [line 16]\n NULLIFY(&this,false); [line 16]\n " color=yellow style=filled] 4 -> 7 ; @@ -36,7 +36,7 @@ digraph iCFG { 2 [label="2: Exit A::AIn_fun \n " color=yellow style=filled] -1 [label="1: Start A::AIn_fun\nFormals: this:class A::AIn \nLocals: \n DECLARE_LOCALS(&return); [line 12]\n NULLIFY(&this,false); [line 12]\n " color=yellow style=filled] +1 [label="1: Start A::AIn_fun\nFormals: this:class A::AIn *\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/methods/overloading.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/methods/overloading.cpp.dot index 05bc80340..78065c4e5 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/methods/overloading.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/methods/overloading.cpp.dot @@ -21,7 +21,7 @@ digraph iCFG { 5 [label="5: Exit A_fun \n " color=yellow style=filled] -4 [label="4: Start A_fun\nFormals: this:class A a:int b:int \nLocals: \n DECLARE_LOCALS(&return); [line 19]\n NULLIFY(&this,false); [line 19]\n " color=yellow style=filled] +4 [label="4: Start A_fun\nFormals: this:class A * a:int b:int \nLocals: \n DECLARE_LOCALS(&return); [line 19]\n NULLIFY(&this,false); [line 19]\n " color=yellow style=filled] 4 -> 6 ; @@ -32,7 +32,7 @@ digraph iCFG { 2 [label="2: Exit A_fun \n " color=yellow style=filled] -1 [label="1: Start A_fun\nFormals: this:class A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 15]\n NULLIFY(&this,false); [line 15]\n " color=yellow style=filled] +1 [label="1: Start A_fun\nFormals: this:class A * a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 15]\n NULLIFY(&this,false); [line 15]\n " color=yellow style=filled] 1 -> 3 ; diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.dot b/infer/tests/codetoanalyze/cpp/frontend/types/inheritance.dot index d0e7add41..2ae86f838 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:class 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:class 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:class 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/frontend/cpp/MethodsTest.java b/infer/tests/frontend/cpp/MethodsTest.java index eab82b7ae..2f1fb07b8 100644 --- a/infer/tests/frontend/cpp/MethodsTest.java +++ b/infer/tests/frontend/cpp/MethodsTest.java @@ -47,5 +47,10 @@ public class MethodsTest { frontendTest("overloading.cpp"); } + @Test + public void testDerefernceThisDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("dereference_this.cpp"); + } }