Add support for C++ this expression

Summary: @​public
1. Add support for `this` keyword. It will allow to access fields/methods of the object from the method body.
2. Fix problem with method formals to add pointer to type of first parameter (which corresponds to `this`)

Reviewed By: @dulmarod

Differential Revision: D2484882

fb-gh-sync-id: c318619
master
Andrzej Kotulski 9 years ago committed by facebook-github-bot-1
parent f8b8078538
commit 4d10c8d9f4

@ -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

@ -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

@ -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 ;

@ -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 ;

@ -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();
}

@ -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 ;
}

@ -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 ;

@ -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 ;

@ -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 ;

@ -47,5 +47,10 @@ public class MethodsTest {
frontendTest("overloading.cpp");
}
@Test
public void testDerefernceThisDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("dereference_this.cpp");
}
}

Loading…
Cancel
Save