Fix handling of C++ references

Summary: @​public
This diff changes following things:
1. expression_info.type_ptr has type than decl_ref_info.type_ptr for reference types. Use type from decl_ref_info as a source of truth
2. reference types need to have one extra dereference that is not in AST. Add handling for this.
3. [small refactor] create function that creates temporary variable from res_trans expression and returns new res_trans.

Some caveats:
1. types are not quite right yet (see .dot files).
2. decl_ref_info might not be set for DeclRefExpr, make frontend crash in that case to catch when this happens

This is high risk change since it changes behavior of every translation on very widely used expr.

Reviewed By: @dulmarod

Differential Revision: D2540632

fb-gh-sync-id: aa28936
master
Andrzej Kotulski 9 years ago committed by facebook-github-bot-1
parent ba00f08f00
commit bfe10e3829

@ -296,7 +296,9 @@ struct
Printing.log_out " priority node free = '%s'\n@."
(string_of_bool (PriorityNode.is_priority_free trans_state));
let context = trans_state.context in
let tp = expr_info.Clang_ast_t.ei_type_ptr in
let pln = trans_state.parent_line_number in
let sil_loc = CLocation.get_sil_location stmt_info pln context in
let tp = get_type_decl_ref_exp_info decl_ref_expr_info in
let typ = CTypes_decl.type_ptr_to_sil_type context.tenv tp in
let name = get_name_decl_ref_exp_info decl_ref_expr_info stmt_info in
let procname = Cfg.Procdesc.get_proc_name context.procdesc in
@ -355,7 +357,11 @@ struct
[(e, typ)]
else [(e, typ)] in
Printing.log_out "\n\n PVAR ='%s'\n\n" (Sil.pvar_to_string pvar);
{ empty_res_trans with exps = exps }
let res_trans = { empty_res_trans with exps = exps } in
if CTypes.is_reference_type tp then
(* dereference pvar due to the behavior of reference types in clang's AST *)
dereference_value_from_result sil_loc res_trans
else res_trans
| _ ->
let print_error decl_kind =
Printing.log_stats
@ -366,7 +372,6 @@ struct
| `CXXMethod -> print_error decl_kind; assert false
| _ -> print_error decl_kind; assert false
let cxxThisExpr_trans trans_state stmt_info expr_info =
let context = trans_state.context in
let pln = trans_state.parent_line_number in
@ -379,10 +384,7 @@ struct
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)] }
dereference_value_from_result sil_loc { empty_res_trans with exps = exps }
let rec labelStmt_trans trans_state stmt_info stmt_list label_name =
(* go ahead with the translation *)

@ -358,6 +358,24 @@ let builtin_trans trans_state loc stmt_info function_type callee_pname_opt =
Some (alloc_trans trans_state loc stmt_info function_type false)
else None
let dereference_var_sil (exp, typ) sil_loc =
let id = Ident.create_fresh Ident.knormal in
let sil_instr = Sil.Letderef (id, exp, typ, sil_loc) in
([id], [sil_instr], Sil.Var id)
(** Given trans_result with ONE expression, create temporary variable with *)
(** value of an expression assigned to it *)
let dereference_value_from_result sil_loc trans_result =
let (obj_sil, class_typ) = extract_exp_from_list trans_result.exps "" in
let cast_ids, cast_inst, cast_exp = dereference_var_sil (obj_sil, class_typ) sil_loc in
let typ_no_ptr = match class_typ with | Sil.Tptr (typ, _) -> typ | _ -> assert false in
{ trans_result with
ids = trans_result.ids @ cast_ids;
instrs = trans_result.instrs @ cast_inst;
exps = [(cast_exp, typ_no_ptr)]
}
let cast_operation context cast_kind exps cast_typ sil_loc is_objc_bridged =
let (exp, typ) = extract_exp_from_list exps "" in
if is_objc_bridged then
@ -373,9 +391,7 @@ let cast_operation context cast_kind exps cast_typ sil_loc is_objc_bridged =
| `LValueToRValue ->
(* Takes an LValue and allow it to use it as RValue. *)
(* So we assign the LValue to a temp and we pass it to the parent.*)
let id = Ident.create_fresh Ident.knormal in
let sil_instr = [Sil.Letderef (id, exp, typ, sil_loc)] in
([id], sil_instr, Sil.Var id)
dereference_var_sil (exp, typ) sil_loc
| `CPointerToObjCPointerCast ->
([], [], Sil.Cast(typ, exp))
| _ ->
@ -451,6 +467,13 @@ let get_name_decl_ref_exp_info decl_ref_expr_info si =
(Clang_ast_j.string_of_decl_ref_expr_info decl_ref_expr_info )
(Clang_ast_j.string_of_stmt_info si); assert false
let get_type_decl_ref_exp_info decl_ref_expr_info =
match decl_ref_expr_info.Clang_ast_t.drti_decl_ref with
| Some d -> (match d.Clang_ast_t.dr_type_ptr with
| Some ptr -> ptr
| _ -> assert false)
| _ -> assert false
let is_superinstance mei =
match mei.Clang_ast_t.omei_receiver_kind with
| `SuperInstance -> true

@ -71,6 +71,8 @@ val compute_instr_ids_exp_to_parent :
val get_name_decl_ref_exp_info : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.stmt_info -> string
val get_type_decl_ref_exp_info : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.type_ptr
val get_decl_kind : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.decl_kind
val get_decl_pointer : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.pointer
@ -81,6 +83,10 @@ val is_member_exp : Clang_ast_t.stmt -> bool
val get_type_from_exp_stmt : Clang_ast_t.stmt -> Clang_ast_t.type_ptr
(** Given trans_result with ONE expression, create temporary variable with *)
(** dereferenced value of an expression assigned to it *)
val dereference_value_from_result : Location.t -> trans_result -> trans_result
val cast_operation :
CContext.t -> Clang_ast_t.cast_kind -> (Sil.exp * Sil.typ) list -> Sil.typ -> Location.t ->
bool -> Ident.t list * Sil.instr list * Sil.exp

@ -104,6 +104,11 @@ let is_block_type tp =
| Some BlockPointerType _ -> true
| _ -> false
let is_reference_type tp =
match Ast_utils.get_desugared_type tp with
| Some Clang_ast_t.LValueReferenceType _ -> true
| _ -> false
(* Expand a named type Tvar if it has a definition in tenv. This is used for Tenum, Tstruct, etc. *)
let rec expand_structured_type tenv typ =
match typ with

@ -31,6 +31,8 @@ val return_type_of_function_type : Clang_ast_t.type_ptr -> Clang_ast_t.type_ptr
val is_block_type : Clang_ast_t.type_ptr -> bool
val is_reference_type : Clang_ast_t.type_ptr -> bool
val expand_structured_type : Sil.tenv -> Sil.typ -> Sil.typ
val get_name_from_type_pointer : string -> string * string

@ -0,0 +1,14 @@
/*
* 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.
*/
void test() {
int v = 3;
int& r = v;
int* p = &v;
}

@ -0,0 +1,21 @@
digraph iCFG {
5 [label="5: DeclStmt \n *&v:int =3 [line 11]\n " shape="box"]
5 -> 4 ;
4 [label="4: DeclStmt \n *&r:int =&v [line 12]\n NULLIFY(&r,false); [line 12]\n " shape="box"]
4 -> 3 ;
3 [label="3: DeclStmt \n *&p:int *=&v [line 13]\n NULLIFY(&p,false); [line 13]\n NULLIFY(&v,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit test \n " color=yellow style=filled]
1 [label="1: Start test\nFormals: \nLocals: p:int * r:int & v:int \n DECLARE_LOCALS(&return,&p,&r,&v); [line 10]\n NULLIFY(&p,false); [line 10]\n NULLIFY(&r,false); [line 10]\n " color=yellow style=filled]
1 -> 5 ;
}

@ -0,0 +1,26 @@
/*
* 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.
*/
void init_from_ref(int &par) {
int v = par;
int& d = par;
int* p = ∥
}
void init_from_val(int par) {
int v = par;
int& d = par;
int* p = ∥
}
void init_from_ptr(int *par) {
int v = *par;
int& d = *par;
int* p = par;
}

@ -0,0 +1,59 @@
digraph iCFG {
15 [label="15: DeclStmt \n n$2=*&par:int * [line 23]\n n$3=*n$2:int [line 23]\n *&v:int =n$3 [line 23]\n REMOVE_TEMPS(n$2,n$3); [line 23]\n NULLIFY(&v,false); [line 23]\n " shape="box"]
15 -> 14 ;
14 [label="14: DeclStmt \n n$1=*&par:int * [line 24]\n *&d:int =n$1 [line 24]\n REMOVE_TEMPS(n$1); [line 24]\n NULLIFY(&d,false); [line 24]\n " shape="box"]
14 -> 13 ;
13 [label="13: DeclStmt \n n$0=*&par:int * [line 25]\n *&p:int *=n$0 [line 25]\n REMOVE_TEMPS(n$0); [line 25]\n NULLIFY(&p,false); [line 25]\n NULLIFY(&par,false); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"]
13 -> 12 ;
12 [label="12: Exit init_from_ptr \n " color=yellow style=filled]
11 [label="11: Start init_from_ptr\nFormals: par:int *\nLocals: p:int * d:int & v:int \n DECLARE_LOCALS(&return,&p,&d,&v); [line 22]\n NULLIFY(&d,false); [line 22]\n NULLIFY(&p,false); [line 22]\n NULLIFY(&v,false); [line 22]\n " color=yellow style=filled]
11 -> 15 ;
10 [label="10: DeclStmt \n n$0=*&par:int [line 17]\n *&v:int =n$0 [line 17]\n REMOVE_TEMPS(n$0); [line 17]\n NULLIFY(&v,false); [line 17]\n " shape="box"]
10 -> 9 ;
9 [label="9: DeclStmt \n *&d:int =&par [line 18]\n NULLIFY(&d,false); [line 18]\n " shape="box"]
9 -> 8 ;
8 [label="8: DeclStmt \n *&p:int *=&par [line 19]\n NULLIFY(&p,false); [line 19]\n NULLIFY(&par,false); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"]
8 -> 7 ;
7 [label="7: Exit init_from_val \n " color=yellow style=filled]
6 [label="6: Start init_from_val\nFormals: par:int \nLocals: p:int * d:int & v:int \n DECLARE_LOCALS(&return,&p,&d,&v); [line 16]\n NULLIFY(&d,false); [line 16]\n NULLIFY(&p,false); [line 16]\n NULLIFY(&v,false); [line 16]\n " color=yellow style=filled]
6 -> 10 ;
5 [label="5: DeclStmt \n n$2=*&par:int & [line 11]\n n$3=*n$2:int [line 11]\n *&v:int =n$3 [line 11]\n REMOVE_TEMPS(n$2,n$3); [line 11]\n NULLIFY(&v,false); [line 11]\n " shape="box"]
5 -> 4 ;
4 [label="4: DeclStmt \n n$1=*&par:int & [line 12]\n *&d:int =n$1 [line 12]\n REMOVE_TEMPS(n$1); [line 12]\n NULLIFY(&d,false); [line 12]\n " shape="box"]
4 -> 3 ;
3 [label="3: DeclStmt \n n$0=*&par:int & [line 13]\n *&p:int *=n$0 [line 13]\n REMOVE_TEMPS(n$0); [line 13]\n NULLIFY(&p,false); [line 13]\n NULLIFY(&par,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit init_from_ref \n " color=yellow style=filled]
1 [label="1: Start init_from_ref\nFormals: par:int &\nLocals: p:int * d:int & v:int \n DECLARE_LOCALS(&return,&p,&d,&v); [line 10]\n NULLIFY(&d,false); [line 10]\n NULLIFY(&p,false); [line 10]\n NULLIFY(&v,false); [line 10]\n " color=yellow style=filled]
1 -> 5 ;
}

@ -0,0 +1,23 @@
/*
* 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.
*/
struct X {
int f;
int call() {return f;}
};
void access_ref(X& x) {
int f = x.f;
int c = x.call();
}
void access_ptr(X* x) {
int f = x->f;
int c = x->call();
}

@ -0,0 +1,43 @@
digraph iCFG {
11 [label="11: DeclStmt \n n$2=*&x:class X * [line 21]\n n$3=*n$2.f:int [line 21]\n *&f:int =n$3 [line 21]\n REMOVE_TEMPS(n$2,n$3); [line 21]\n NULLIFY(&f,false); [line 21]\n " shape="box"]
11 -> 10 ;
10 [label="10: DeclStmt \n n$0=*&x:class X * [line 22]\n n$1=_fun_X_call(n$0:class X ) [line 22]\n *&c:int =n$1 [line 22]\n REMOVE_TEMPS(n$0,n$1); [line 22]\n NULLIFY(&c,false); [line 22]\n NULLIFY(&x,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"]
10 -> 9 ;
9 [label="9: Exit access_ptr \n " color=yellow style=filled]
8 [label="8: Start access_ptr\nFormals: x:class X *\nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 20]\n NULLIFY(&c,false); [line 20]\n NULLIFY(&f,false); [line 20]\n " color=yellow style=filled]
8 -> 11 ;
7 [label="7: DeclStmt \n n$2=*&x:class X & [line 16]\n n$3=*n$2.f:int [line 16]\n *&f:int =n$3 [line 16]\n REMOVE_TEMPS(n$2,n$3); [line 16]\n NULLIFY(&f,false); [line 16]\n " shape="box"]
7 -> 6 ;
6 [label="6: DeclStmt \n n$0=*&x:class X & [line 17]\n n$1=_fun_X_call(n$0:class X ) [line 17]\n *&c:int =n$1 [line 17]\n REMOVE_TEMPS(n$0,n$1); [line 17]\n NULLIFY(&c,false); [line 17]\n NULLIFY(&x,false); [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit access_ref \n " color=yellow style=filled]
4 [label="4: Start access_ref\nFormals: x:class X &\nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 15]\n NULLIFY(&c,false); [line 15]\n NULLIFY(&f,false); [line 15]\n " color=yellow style=filled]
4 -> 7 ;
3 [label="3: Return Stmt \n n$0=*&this:class X * [line 12]\n n$1=*n$0.f:int [line 12]\n *&return:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit X_call \n " color=yellow style=filled]
1 [label="1: Start X_call\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,27 @@
/*
* 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.
*/
struct X {
int f;
int call() {return f;}
};
X global;
X * get_ptr() {return &global;}
X& get_ref() {return global;}
void test_ref() {
int f = get_ref().f;
int c = get_ref().call();
}
void test_ptr() {
int f = get_ptr()->f;
int c = get_ptr()->call();
}

@ -0,0 +1,65 @@
digraph iCFG {
17 [label="17: DeclStmt \n n$2=_fun_get_ptr() [line 25]\n n$3=*n$2.f:int [line 25]\n *&f:int =n$3 [line 25]\n REMOVE_TEMPS(n$2,n$3); [line 25]\n NULLIFY(&f,false); [line 25]\n " shape="box"]
17 -> 16 ;
16 [label="16: DeclStmt \n n$0=_fun_get_ptr() [line 26]\n n$1=_fun_X_call(n$0:class X ) [line 26]\n *&c:int =n$1 [line 26]\n REMOVE_TEMPS(n$0,n$1); [line 26]\n NULLIFY(&c,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"]
16 -> 15 ;
15 [label="15: Exit test_ptr \n " color=yellow style=filled]
14 [label="14: Start test_ptr\nFormals: \nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 24]\n NULLIFY(&c,false); [line 24]\n NULLIFY(&f,false); [line 24]\n " color=yellow style=filled]
14 -> 17 ;
13 [label="13: DeclStmt \n n$2=_fun_get_ref() [line 20]\n n$3=*n$2.f:int [line 20]\n *&f:int =n$3 [line 20]\n REMOVE_TEMPS(n$2,n$3); [line 20]\n NULLIFY(&f,false); [line 20]\n " shape="box"]
13 -> 12 ;
12 [label="12: DeclStmt \n n$0=_fun_get_ref() [line 21]\n n$1=_fun_X_call(n$0:class X ) [line 21]\n *&c:int =n$1 [line 21]\n REMOVE_TEMPS(n$0,n$1); [line 21]\n NULLIFY(&c,false); [line 21]\n APPLY_ABSTRACTION; [line 21]\n " shape="box"]
12 -> 11 ;
11 [label="11: Exit test_ref \n " color=yellow style=filled]
10 [label="10: Start test_ref\nFormals: \nLocals: c:int f:int \n DECLARE_LOCALS(&return,&c,&f); [line 19]\n NULLIFY(&c,false); [line 19]\n NULLIFY(&f,false); [line 19]\n " color=yellow style=filled]
10 -> 13 ;
9 [label="9: Return Stmt \n *&return:class X &=&#GB$global [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"]
9 -> 8 ;
8 [label="8: Exit get_ref \n " color=yellow style=filled]
7 [label="7: Start get_ref\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 17]\n " color=yellow style=filled]
7 -> 9 ;
6 [label="6: Return Stmt \n *&return:class X *=&#GB$global [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit get_ptr \n " color=yellow style=filled]
4 [label="4: Start get_ptr\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 16]\n " color=yellow style=filled]
4 -> 6 ;
3 [label="3: Return Stmt \n n$0=*&this:class X * [line 12]\n n$1=*n$0.f:int [line 12]\n *&return:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit X_call \n " color=yellow style=filled]
1 [label="1: Start X_call\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,139 @@
/*
* 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.
*/
struct X {
int f;
void nonzero() { f = 1; }
void zero() { f = 0; }
int div() { return 1/f; }
};
void zero_ptr(X *x) {
x->zero();
}
void nonzero_ptr(X *x) {
x->nonzero();
}
void set_field_ptr(X *x, int val) {
x->f = val;
}
void zero_ref(X &x) {
x.zero();
}
void nonzero_ref(X &x) {
x.nonzero();
}
void set_field_ref(X &x, int val) {
x.f = val;
}
X global;
X* get_global_ptr() { return &global;}
X& get_global_ref() { return global;}
int method_div0_ptr(X *x) {
if (x) {
zero_ptr(x);
return x->div();
}
}
int method_div1_ptr(X *x) {
if (x) {
nonzero_ptr(x);
return x->div();
}
}
int field_div0_ptr(X *x) {
if(x) {
set_field_ptr(x, 0);
return x->div();
}
}
int field_div1_ptr(X *x) {
if(x) {
set_field_ptr(x, 1);
return x->div();
}
}
int get_global_ptr_div0_method() {
get_global_ptr()->f = 1;
get_global_ptr()->zero();
get_global_ptr()->div();
}
int get_global_ptr_div1_method() {
get_global_ptr()->f = 0;
get_global_ptr()->nonzero();
get_global_ptr()->div();
}
int get_global_ptr_div0_field() {
get_global_ptr()->nonzero();
get_global_ptr()->f = 0;
get_global_ptr()->div();
}
int get_global_ptr_div1_field() {
get_global_ptr()->zero();
get_global_ptr()->f = 1;
get_global_ptr()->div();
}
int method_div0_ref(X &x) {
zero_ref(x);
return x.div();
}
int method_div1_ref(X &x) {
nonzero_ref(x);
return x.div();
}
int field_div0_ref(X &x) {
set_field_ref(x, 0);
return x.div();
}
int field_div1_ref(X &x) {
set_field_ref(x, 1);
return x.div();
}
int get_global_ref_div0_method() {
get_global_ref().f = 1;
get_global_ref().zero();
get_global_ref().div();
}
int get_global_ref_div1_method() {
get_global_ref().f = 0;
get_global_ref().nonzero();
get_global_ref().div();
}
int get_global_ref_div0_field() {
get_global_ref().nonzero();
get_global_ref().f = 0;
get_global_ref().div();
}
int get_global_ref_div1_field() {
get_global_ref().zero();
get_global_ref().f = 1;
get_global_ref().div();
}

@ -0,0 +1,447 @@
digraph iCFG {
117 [label="117: Call _fun_X_zero \n n$3=_fun_get_global_ref() [line 136]\n _fun_X_zero(n$3:class X ) [line 136]\n REMOVE_TEMPS(n$3); [line 136]\n " shape="box"]
117 -> 116 ;
116 [label="116: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ref() [line 137]\n *n$2.f:int =1 [line 137]\n REMOVE_TEMPS(n$2); [line 137]\n " shape="box"]
116 -> 115 ;
115 [label="115: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 138]\n n$1=_fun_X_div(n$0:class X ) [line 138]\n REMOVE_TEMPS(n$0,n$1); [line 138]\n APPLY_ABSTRACTION; [line 138]\n " shape="box"]
115 -> 114 ;
114 [label="114: Exit get_global_ref_div1_field \n " color=yellow style=filled]
113 [label="113: Start get_global_ref_div1_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 135]\n " color=yellow style=filled]
113 -> 117 ;
112 [label="112: Call _fun_X_nonzero \n n$3=_fun_get_global_ref() [line 130]\n _fun_X_nonzero(n$3:class X ) [line 130]\n REMOVE_TEMPS(n$3); [line 130]\n " shape="box"]
112 -> 111 ;
111 [label="111: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ref() [line 131]\n *n$2.f:int =0 [line 131]\n REMOVE_TEMPS(n$2); [line 131]\n " shape="box"]
111 -> 110 ;
110 [label="110: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 132]\n n$1=_fun_X_div(n$0:class X ) [line 132]\n REMOVE_TEMPS(n$0,n$1); [line 132]\n APPLY_ABSTRACTION; [line 132]\n " shape="box"]
110 -> 109 ;
109 [label="109: Exit get_global_ref_div0_field \n " color=yellow style=filled]
108 [label="108: Start get_global_ref_div0_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 129]\n " color=yellow style=filled]
108 -> 112 ;
107 [label="107: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ref() [line 124]\n *n$3.f:int =0 [line 124]\n REMOVE_TEMPS(n$3); [line 124]\n " shape="box"]
107 -> 106 ;
106 [label="106: Call _fun_X_nonzero \n n$2=_fun_get_global_ref() [line 125]\n _fun_X_nonzero(n$2:class X ) [line 125]\n REMOVE_TEMPS(n$2); [line 125]\n " shape="box"]
106 -> 105 ;
105 [label="105: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 126]\n n$1=_fun_X_div(n$0:class X ) [line 126]\n REMOVE_TEMPS(n$0,n$1); [line 126]\n APPLY_ABSTRACTION; [line 126]\n " shape="box"]
105 -> 104 ;
104 [label="104: Exit get_global_ref_div1_method \n " color=yellow style=filled]
103 [label="103: Start get_global_ref_div1_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 123]\n " color=yellow style=filled]
103 -> 107 ;
102 [label="102: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ref() [line 118]\n *n$3.f:int =1 [line 118]\n REMOVE_TEMPS(n$3); [line 118]\n " shape="box"]
102 -> 101 ;
101 [label="101: Call _fun_X_zero \n n$2=_fun_get_global_ref() [line 119]\n _fun_X_zero(n$2:class X ) [line 119]\n REMOVE_TEMPS(n$2); [line 119]\n " shape="box"]
101 -> 100 ;
100 [label="100: Call _fun_X_div \n n$0=_fun_get_global_ref() [line 120]\n n$1=_fun_X_div(n$0:class X ) [line 120]\n REMOVE_TEMPS(n$0,n$1); [line 120]\n APPLY_ABSTRACTION; [line 120]\n " shape="box"]
100 -> 99 ;
99 [label="99: Exit get_global_ref_div0_method \n " color=yellow style=filled]
98 [label="98: Start get_global_ref_div0_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 117]\n " color=yellow style=filled]
98 -> 102 ;
97 [label="97: Call _fun_set_field_ref \n n$2=*&x:class X & [line 113]\n _fun_set_field_ref(n$2:class X ,1:int ) [line 113]\n REMOVE_TEMPS(n$2); [line 113]\n " shape="box"]
97 -> 96 ;
96 [label="96: Return Stmt \n n$0=*&x:class X & [line 114]\n n$1=_fun_X_div(n$0:class X ) [line 114]\n *&return:int =n$1 [line 114]\n REMOVE_TEMPS(n$0,n$1); [line 114]\n NULLIFY(&x,false); [line 114]\n APPLY_ABSTRACTION; [line 114]\n " shape="box"]
96 -> 95 ;
95 [label="95: Exit field_div1_ref \n " color=yellow style=filled]
94 [label="94: Start field_div1_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 112]\n " color=yellow style=filled]
94 -> 97 ;
93 [label="93: Call _fun_set_field_ref \n n$2=*&x:class X & [line 108]\n _fun_set_field_ref(n$2:class X ,0:int ) [line 108]\n REMOVE_TEMPS(n$2); [line 108]\n " shape="box"]
93 -> 92 ;
92 [label="92: Return Stmt \n n$0=*&x:class X & [line 109]\n n$1=_fun_X_div(n$0:class X ) [line 109]\n *&return:int =n$1 [line 109]\n REMOVE_TEMPS(n$0,n$1); [line 109]\n NULLIFY(&x,false); [line 109]\n APPLY_ABSTRACTION; [line 109]\n " shape="box"]
92 -> 91 ;
91 [label="91: Exit field_div0_ref \n " color=yellow style=filled]
90 [label="90: Start field_div0_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 107]\n " color=yellow style=filled]
90 -> 93 ;
89 [label="89: Call _fun_nonzero_ref \n n$2=*&x:class X & [line 103]\n _fun_nonzero_ref(n$2:class X ) [line 103]\n REMOVE_TEMPS(n$2); [line 103]\n " shape="box"]
89 -> 88 ;
88 [label="88: Return Stmt \n n$0=*&x:class X & [line 104]\n n$1=_fun_X_div(n$0:class X ) [line 104]\n *&return:int =n$1 [line 104]\n REMOVE_TEMPS(n$0,n$1); [line 104]\n NULLIFY(&x,false); [line 104]\n APPLY_ABSTRACTION; [line 104]\n " shape="box"]
88 -> 87 ;
87 [label="87: Exit method_div1_ref \n " color=yellow style=filled]
86 [label="86: Start method_div1_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 102]\n " color=yellow style=filled]
86 -> 89 ;
85 [label="85: Call _fun_zero_ref \n n$2=*&x:class X & [line 98]\n _fun_zero_ref(n$2:class X ) [line 98]\n REMOVE_TEMPS(n$2); [line 98]\n " shape="box"]
85 -> 84 ;
84 [label="84: Return Stmt \n n$0=*&x:class X & [line 99]\n n$1=_fun_X_div(n$0:class X ) [line 99]\n *&return:int =n$1 [line 99]\n REMOVE_TEMPS(n$0,n$1); [line 99]\n NULLIFY(&x,false); [line 99]\n APPLY_ABSTRACTION; [line 99]\n " shape="box"]
84 -> 83 ;
83 [label="83: Exit method_div0_ref \n " color=yellow style=filled]
82 [label="82: Start method_div0_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 97]\n " color=yellow style=filled]
82 -> 85 ;
81 [label="81: Call _fun_X_zero \n n$3=_fun_get_global_ptr() [line 92]\n _fun_X_zero(n$3:class X ) [line 92]\n REMOVE_TEMPS(n$3); [line 92]\n " shape="box"]
81 -> 80 ;
80 [label="80: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ptr() [line 93]\n *n$2.f:int =1 [line 93]\n REMOVE_TEMPS(n$2); [line 93]\n " shape="box"]
80 -> 79 ;
79 [label="79: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 94]\n n$1=_fun_X_div(n$0:class X ) [line 94]\n REMOVE_TEMPS(n$0,n$1); [line 94]\n APPLY_ABSTRACTION; [line 94]\n " shape="box"]
79 -> 78 ;
78 [label="78: Exit get_global_ptr_div1_field \n " color=yellow style=filled]
77 [label="77: Start get_global_ptr_div1_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 91]\n " color=yellow style=filled]
77 -> 81 ;
76 [label="76: Call _fun_X_nonzero \n n$3=_fun_get_global_ptr() [line 86]\n _fun_X_nonzero(n$3:class X ) [line 86]\n REMOVE_TEMPS(n$3); [line 86]\n " shape="box"]
76 -> 75 ;
75 [label="75: BinaryOperatorStmt: Assign \n n$2=_fun_get_global_ptr() [line 87]\n *n$2.f:int =0 [line 87]\n REMOVE_TEMPS(n$2); [line 87]\n " shape="box"]
75 -> 74 ;
74 [label="74: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 88]\n n$1=_fun_X_div(n$0:class X ) [line 88]\n REMOVE_TEMPS(n$0,n$1); [line 88]\n APPLY_ABSTRACTION; [line 88]\n " shape="box"]
74 -> 73 ;
73 [label="73: Exit get_global_ptr_div0_field \n " color=yellow style=filled]
72 [label="72: Start get_global_ptr_div0_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 85]\n " color=yellow style=filled]
72 -> 76 ;
71 [label="71: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ptr() [line 80]\n *n$3.f:int =0 [line 80]\n REMOVE_TEMPS(n$3); [line 80]\n " shape="box"]
71 -> 70 ;
70 [label="70: Call _fun_X_nonzero \n n$2=_fun_get_global_ptr() [line 81]\n _fun_X_nonzero(n$2:class X ) [line 81]\n REMOVE_TEMPS(n$2); [line 81]\n " shape="box"]
70 -> 69 ;
69 [label="69: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 82]\n n$1=_fun_X_div(n$0:class X ) [line 82]\n REMOVE_TEMPS(n$0,n$1); [line 82]\n APPLY_ABSTRACTION; [line 82]\n " shape="box"]
69 -> 68 ;
68 [label="68: Exit get_global_ptr_div1_method \n " color=yellow style=filled]
67 [label="67: Start get_global_ptr_div1_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 79]\n " color=yellow style=filled]
67 -> 71 ;
66 [label="66: BinaryOperatorStmt: Assign \n n$3=_fun_get_global_ptr() [line 74]\n *n$3.f:int =1 [line 74]\n REMOVE_TEMPS(n$3); [line 74]\n " shape="box"]
66 -> 65 ;
65 [label="65: Call _fun_X_zero \n n$2=_fun_get_global_ptr() [line 75]\n _fun_X_zero(n$2:class X ) [line 75]\n REMOVE_TEMPS(n$2); [line 75]\n " shape="box"]
65 -> 64 ;
64 [label="64: Call _fun_X_div \n n$0=_fun_get_global_ptr() [line 76]\n n$1=_fun_X_div(n$0:class X ) [line 76]\n REMOVE_TEMPS(n$0,n$1); [line 76]\n APPLY_ABSTRACTION; [line 76]\n " shape="box"]
64 -> 63 ;
63 [label="63: Exit get_global_ptr_div0_method \n " color=yellow style=filled]
62 [label="62: Start get_global_ptr_div0_method\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 73]\n " color=yellow style=filled]
62 -> 66 ;
61 [label="61: Call _fun_set_field_ptr \n n$3=*&x:class X * [line 68]\n _fun_set_field_ptr(n$3:class X *,1:int ) [line 68]\n REMOVE_TEMPS(n$3); [line 68]\n " shape="box"]
61 -> 60 ;
60 [label="60: Return Stmt \n n$1=*&x:class X * [line 69]\n n$2=_fun_X_div(n$1:class X ) [line 69]\n *&return:int =n$2 [line 69]\n REMOVE_TEMPS(n$1,n$2); [line 69]\n NULLIFY(&x,false); [line 69]\n APPLY_ABSTRACTION; [line 69]\n " shape="box"]
60 -> 56 ;
59 [label="59: Prune (false branch) \n n$0=*&x:class X * [line 67]\n PRUNE((n$0 == 0), false); [line 67]\n REMOVE_TEMPS(n$0); [line 67]\n " shape="invhouse"]
59 -> 57 ;
58 [label="58: Prune (true branch) \n n$0=*&x:class X * [line 67]\n PRUNE((n$0 != 0), true); [line 67]\n REMOVE_TEMPS(n$0); [line 67]\n " shape="invhouse"]
58 -> 61 ;
57 [label="57: + \n NULLIFY(&x,false); [line 67]\n " ]
57 -> 56 ;
56 [label="56: Exit field_div1_ptr \n " color=yellow style=filled]
55 [label="55: Start field_div1_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 66]\n " color=yellow style=filled]
55 -> 58 ;
55 -> 59 ;
54 [label="54: Call _fun_set_field_ptr \n n$3=*&x:class X * [line 61]\n _fun_set_field_ptr(n$3:class X *,0:int ) [line 61]\n REMOVE_TEMPS(n$3); [line 61]\n " shape="box"]
54 -> 53 ;
53 [label="53: Return Stmt \n n$1=*&x:class X * [line 62]\n n$2=_fun_X_div(n$1:class X ) [line 62]\n *&return:int =n$2 [line 62]\n REMOVE_TEMPS(n$1,n$2); [line 62]\n NULLIFY(&x,false); [line 62]\n APPLY_ABSTRACTION; [line 62]\n " shape="box"]
53 -> 49 ;
52 [label="52: Prune (false branch) \n n$0=*&x:class X * [line 60]\n PRUNE((n$0 == 0), false); [line 60]\n REMOVE_TEMPS(n$0); [line 60]\n " shape="invhouse"]
52 -> 50 ;
51 [label="51: Prune (true branch) \n n$0=*&x:class X * [line 60]\n PRUNE((n$0 != 0), true); [line 60]\n REMOVE_TEMPS(n$0); [line 60]\n " shape="invhouse"]
51 -> 54 ;
50 [label="50: + \n NULLIFY(&x,false); [line 60]\n " ]
50 -> 49 ;
49 [label="49: Exit field_div0_ptr \n " color=yellow style=filled]
48 [label="48: Start field_div0_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 59]\n " color=yellow style=filled]
48 -> 51 ;
48 -> 52 ;
47 [label="47: Call _fun_nonzero_ptr \n n$3=*&x:class X * [line 54]\n _fun_nonzero_ptr(n$3:class X *) [line 54]\n REMOVE_TEMPS(n$3); [line 54]\n " shape="box"]
47 -> 46 ;
46 [label="46: Return Stmt \n n$1=*&x:class X * [line 55]\n n$2=_fun_X_div(n$1:class X ) [line 55]\n *&return:int =n$2 [line 55]\n REMOVE_TEMPS(n$1,n$2); [line 55]\n NULLIFY(&x,false); [line 55]\n APPLY_ABSTRACTION; [line 55]\n " shape="box"]
46 -> 42 ;
45 [label="45: Prune (false branch) \n n$0=*&x:class X * [line 53]\n PRUNE((n$0 == 0), false); [line 53]\n REMOVE_TEMPS(n$0); [line 53]\n " shape="invhouse"]
45 -> 43 ;
44 [label="44: Prune (true branch) \n n$0=*&x:class X * [line 53]\n PRUNE((n$0 != 0), true); [line 53]\n REMOVE_TEMPS(n$0); [line 53]\n " shape="invhouse"]
44 -> 47 ;
43 [label="43: + \n NULLIFY(&x,false); [line 53]\n " ]
43 -> 42 ;
42 [label="42: Exit method_div1_ptr \n " color=yellow style=filled]
41 [label="41: Start method_div1_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 52]\n " color=yellow style=filled]
41 -> 44 ;
41 -> 45 ;
40 [label="40: Call _fun_zero_ptr \n n$3=*&x:class X * [line 47]\n _fun_zero_ptr(n$3:class X *) [line 47]\n REMOVE_TEMPS(n$3); [line 47]\n " shape="box"]
40 -> 39 ;
39 [label="39: Return Stmt \n n$1=*&x:class X * [line 48]\n n$2=_fun_X_div(n$1:class X ) [line 48]\n *&return:int =n$2 [line 48]\n REMOVE_TEMPS(n$1,n$2); [line 48]\n NULLIFY(&x,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"]
39 -> 35 ;
38 [label="38: Prune (false branch) \n n$0=*&x:class X * [line 46]\n PRUNE((n$0 == 0), false); [line 46]\n REMOVE_TEMPS(n$0); [line 46]\n " shape="invhouse"]
38 -> 36 ;
37 [label="37: Prune (true branch) \n n$0=*&x:class X * [line 46]\n PRUNE((n$0 != 0), true); [line 46]\n REMOVE_TEMPS(n$0); [line 46]\n " shape="invhouse"]
37 -> 40 ;
36 [label="36: + \n NULLIFY(&x,false); [line 46]\n " ]
36 -> 35 ;
35 [label="35: Exit method_div0_ptr \n " color=yellow style=filled]
34 [label="34: Start method_div0_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 45]\n " color=yellow style=filled]
34 -> 37 ;
34 -> 38 ;
33 [label="33: Return Stmt \n *&return:class X &=&#GB$global [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"]
33 -> 32 ;
32 [label="32: Exit get_global_ref \n " color=yellow style=filled]
31 [label="31: Start get_global_ref\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 43]\n " color=yellow style=filled]
31 -> 33 ;
30 [label="30: Return Stmt \n *&return:class X *=&#GB$global [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"]
30 -> 29 ;
29 [label="29: Exit get_global_ptr \n " color=yellow style=filled]
28 [label="28: Start get_global_ptr\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 42]\n " color=yellow style=filled]
28 -> 30 ;
27 [label="27: BinaryOperatorStmt: Assign \n n$0=*&x:class X & [line 38]\n n$1=*&val:int [line 38]\n *n$0.f:int =n$1 [line 38]\n REMOVE_TEMPS(n$0,n$1); [line 38]\n NULLIFY(&val,false); [line 38]\n NULLIFY(&x,false); [line 38]\n APPLY_ABSTRACTION; [line 38]\n " shape="box"]
27 -> 26 ;
26 [label="26: Exit set_field_ref \n " color=yellow style=filled]
25 [label="25: Start set_field_ref\nFormals: x:class X & val:int \nLocals: \n DECLARE_LOCALS(&return); [line 37]\n " color=yellow style=filled]
25 -> 27 ;
24 [label="24: Call _fun_X_nonzero \n n$0=*&x:class X & [line 34]\n _fun_X_nonzero(n$0:class X ) [line 34]\n REMOVE_TEMPS(n$0); [line 34]\n NULLIFY(&x,false); [line 34]\n APPLY_ABSTRACTION; [line 34]\n " shape="box"]
24 -> 23 ;
23 [label="23: Exit nonzero_ref \n " color=yellow style=filled]
22 [label="22: Start nonzero_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 33]\n " color=yellow style=filled]
22 -> 24 ;
21 [label="21: Call _fun_X_zero \n n$0=*&x:class X & [line 30]\n _fun_X_zero(n$0:class X ) [line 30]\n REMOVE_TEMPS(n$0); [line 30]\n NULLIFY(&x,false); [line 30]\n APPLY_ABSTRACTION; [line 30]\n " shape="box"]
21 -> 20 ;
20 [label="20: Exit zero_ref \n " color=yellow style=filled]
19 [label="19: Start zero_ref\nFormals: x:class X &\nLocals: \n DECLARE_LOCALS(&return); [line 29]\n " color=yellow style=filled]
19 -> 21 ;
18 [label="18: BinaryOperatorStmt: Assign \n n$0=*&x:class X * [line 26]\n n$1=*&val:int [line 26]\n *n$0.f:int =n$1 [line 26]\n REMOVE_TEMPS(n$0,n$1); [line 26]\n NULLIFY(&val,false); [line 26]\n NULLIFY(&x,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"]
18 -> 17 ;
17 [label="17: Exit set_field_ptr \n " color=yellow style=filled]
16 [label="16: Start set_field_ptr\nFormals: x:class X * val:int \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n " color=yellow style=filled]
16 -> 18 ;
15 [label="15: Call _fun_X_nonzero \n n$0=*&x:class X * [line 22]\n _fun_X_nonzero(n$0:class X ) [line 22]\n REMOVE_TEMPS(n$0); [line 22]\n NULLIFY(&x,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"]
15 -> 14 ;
14 [label="14: Exit nonzero_ptr \n " color=yellow style=filled]
13 [label="13: Start nonzero_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 21]\n " color=yellow style=filled]
13 -> 15 ;
12 [label="12: Call _fun_X_zero \n n$0=*&x:class X * [line 18]\n _fun_X_zero(n$0:class X ) [line 18]\n REMOVE_TEMPS(n$0); [line 18]\n NULLIFY(&x,false); [line 18]\n APPLY_ABSTRACTION; [line 18]\n " shape="box"]
12 -> 11 ;
11 [label="11: Exit zero_ptr \n " color=yellow style=filled]
10 [label="10: Start zero_ptr\nFormals: x:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 17]\n " color=yellow style=filled]
10 -> 12 ;
9 [label="9: Return Stmt \n n$0=*&this:class X * [line 14]\n n$1=*n$0.f:int [line 14]\n *&return:int =(1 / n$1) [line 14]\n REMOVE_TEMPS(n$0,n$1); [line 14]\n NULLIFY(&this,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"]
9 -> 8 ;
8 [label="8: Exit X_div \n " color=yellow style=filled]
7 [label="7: Start X_div\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled]
7 -> 9 ;
6 [label="6: BinaryOperatorStmt: Assign \n n$0=*&this:class X * [line 13]\n *n$0.f:int =0 [line 13]\n REMOVE_TEMPS(n$0); [line 13]\n NULLIFY(&this,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit X_zero \n " color=yellow style=filled]
4 [label="4: Start X_zero\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
4 -> 6 ;
3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&this:class X * [line 12]\n *n$0.f:int =1 [line 12]\n REMOVE_TEMPS(n$0); [line 12]\n NULLIFY(&this,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit X_nonzero \n " color=yellow style=filled]
1 [label="1: Start X_nonzero\nFormals: this:class X *\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,51 @@
/*
* 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.
*/
void zero_ptr(int* p) { *p = 0; }
void zero_ref(int& p) { p = 0; }
int ptr_div0() {
int a = 2;
int* p = &a;
*p = 0;
return 1/a;
}
int ptr_div0_function() {
int a = 2;
zero_ptr(&a);
return 1/a;
}
int ptr_div0_function_temp_var() {
int a = 2;
int *r = &a;
zero_ptr(r);
return 1/a;
}
int ref_div0() {
int a = 2;
int& r = a;
r = 0;
return 1/a;
}
int ref_div0_function() {
int a = 2;
zero_ref(a);
return 1/a;
}
int ref_div0_function_temp_var() {
int a = 2;
int &r = a;
zero_ref(r);
return 1/a;
}

@ -0,0 +1,154 @@
digraph iCFG {
40 [label="40: DeclStmt \n *&a:int =2 [line 47]\n " shape="box"]
40 -> 39 ;
39 [label="39: DeclStmt \n *&r:int =&a [line 48]\n " shape="box"]
39 -> 38 ;
38 [label="38: Call _fun_zero_ref \n n$1=*&r:int & [line 49]\n _fun_zero_ref(n$1:int ) [line 49]\n REMOVE_TEMPS(n$1); [line 49]\n NULLIFY(&r,false); [line 49]\n " shape="box"]
38 -> 37 ;
37 [label="37: Return Stmt \n n$0=*&a:int [line 50]\n *&return:int =(1 / n$0) [line 50]\n REMOVE_TEMPS(n$0); [line 50]\n NULLIFY(&a,false); [line 50]\n APPLY_ABSTRACTION; [line 50]\n " shape="box"]
37 -> 36 ;
36 [label="36: Exit ref_div0_function_temp_var \n " color=yellow style=filled]
35 [label="35: Start ref_div0_function_temp_var\nFormals: \nLocals: r:int & a:int \n DECLARE_LOCALS(&return,&r,&a); [line 46]\n NULLIFY(&r,false); [line 46]\n " color=yellow style=filled]
35 -> 40 ;
34 [label="34: DeclStmt \n *&a:int =2 [line 41]\n " shape="box"]
34 -> 33 ;
33 [label="33: Call _fun_zero_ref \n _fun_zero_ref(&a:int ) [line 42]\n " shape="box"]
33 -> 32 ;
32 [label="32: Return Stmt \n n$0=*&a:int [line 43]\n *&return:int =(1 / n$0) [line 43]\n REMOVE_TEMPS(n$0); [line 43]\n NULLIFY(&a,false); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"]
32 -> 31 ;
31 [label="31: Exit ref_div0_function \n " color=yellow style=filled]
30 [label="30: Start ref_div0_function\nFormals: \nLocals: a:int \n DECLARE_LOCALS(&return,&a); [line 40]\n " color=yellow style=filled]
30 -> 34 ;
29 [label="29: DeclStmt \n *&a:int =2 [line 34]\n " shape="box"]
29 -> 28 ;
28 [label="28: DeclStmt \n *&r:int =&a [line 35]\n " shape="box"]
28 -> 27 ;
27 [label="27: BinaryOperatorStmt: Assign \n n$1=*&r:int & [line 36]\n *n$1:int =0 [line 36]\n REMOVE_TEMPS(n$1); [line 36]\n NULLIFY(&r,false); [line 36]\n " shape="box"]
27 -> 26 ;
26 [label="26: Return Stmt \n n$0=*&a:int [line 37]\n *&return:int =(1 / n$0) [line 37]\n REMOVE_TEMPS(n$0); [line 37]\n NULLIFY(&a,false); [line 37]\n APPLY_ABSTRACTION; [line 37]\n " shape="box"]
26 -> 25 ;
25 [label="25: Exit ref_div0 \n " color=yellow style=filled]
24 [label="24: Start ref_div0\nFormals: \nLocals: r:int & a:int \n DECLARE_LOCALS(&return,&r,&a); [line 33]\n NULLIFY(&r,false); [line 33]\n " color=yellow style=filled]
24 -> 29 ;
23 [label="23: DeclStmt \n *&a:int =2 [line 27]\n " shape="box"]
23 -> 22 ;
22 [label="22: DeclStmt \n *&r:int *=&a [line 28]\n " shape="box"]
22 -> 21 ;
21 [label="21: Call _fun_zero_ptr \n n$1=*&r:int * [line 29]\n _fun_zero_ptr(n$1:int *) [line 29]\n REMOVE_TEMPS(n$1); [line 29]\n NULLIFY(&r,false); [line 29]\n " shape="box"]
21 -> 20 ;
20 [label="20: Return Stmt \n n$0=*&a:int [line 30]\n *&return:int =(1 / n$0) [line 30]\n REMOVE_TEMPS(n$0); [line 30]\n NULLIFY(&a,false); [line 30]\n APPLY_ABSTRACTION; [line 30]\n " shape="box"]
20 -> 19 ;
19 [label="19: Exit ptr_div0_function_temp_var \n " color=yellow style=filled]
18 [label="18: Start ptr_div0_function_temp_var\nFormals: \nLocals: r:int * a:int \n DECLARE_LOCALS(&return,&r,&a); [line 26]\n NULLIFY(&r,false); [line 26]\n " color=yellow style=filled]
18 -> 23 ;
17 [label="17: DeclStmt \n *&a:int =2 [line 21]\n " shape="box"]
17 -> 16 ;
16 [label="16: Call _fun_zero_ptr \n _fun_zero_ptr(&a:int *) [line 22]\n " shape="box"]
16 -> 15 ;
15 [label="15: Return Stmt \n n$0=*&a:int [line 23]\n *&return:int =(1 / n$0) [line 23]\n REMOVE_TEMPS(n$0); [line 23]\n NULLIFY(&a,false); [line 23]\n APPLY_ABSTRACTION; [line 23]\n " shape="box"]
15 -> 14 ;
14 [label="14: Exit ptr_div0_function \n " color=yellow style=filled]
13 [label="13: Start ptr_div0_function\nFormals: \nLocals: a:int \n DECLARE_LOCALS(&return,&a); [line 20]\n " color=yellow style=filled]
13 -> 17 ;
12 [label="12: DeclStmt \n *&a:int =2 [line 14]\n " shape="box"]
12 -> 11 ;
11 [label="11: DeclStmt \n *&p:int *=&a [line 15]\n " shape="box"]
11 -> 10 ;
10 [label="10: BinaryOperatorStmt: Assign \n n$1=*&p:int * [line 16]\n *n$1:int =0 [line 16]\n REMOVE_TEMPS(n$1); [line 16]\n NULLIFY(&p,false); [line 16]\n " shape="box"]
10 -> 9 ;
9 [label="9: Return Stmt \n n$0=*&a:int [line 17]\n *&return:int =(1 / n$0) [line 17]\n REMOVE_TEMPS(n$0); [line 17]\n NULLIFY(&a,false); [line 17]\n APPLY_ABSTRACTION; [line 17]\n " shape="box"]
9 -> 8 ;
8 [label="8: Exit ptr_div0 \n " color=yellow style=filled]
7 [label="7: Start ptr_div0\nFormals: \nLocals: p:int * a:int \n DECLARE_LOCALS(&return,&p,&a); [line 13]\n NULLIFY(&p,false); [line 13]\n " color=yellow style=filled]
7 -> 12 ;
6 [label="6: BinaryOperatorStmt: Assign \n n$0=*&p:int & [line 11]\n *n$0:int =0 [line 11]\n REMOVE_TEMPS(n$0); [line 11]\n NULLIFY(&p,false); [line 11]\n APPLY_ABSTRACTION; [line 11]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit zero_ref \n " color=yellow style=filled]
4 [label="4: Start zero_ref\nFormals: p:int &\nLocals: \n DECLARE_LOCALS(&return); [line 11]\n " color=yellow style=filled]
4 -> 6 ;
3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&p:int * [line 10]\n *n$0:int =0 [line 10]\n REMOVE_TEMPS(n$0); [line 10]\n NULLIFY(&p,false); [line 10]\n APPLY_ABSTRACTION; [line 10]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit zero_ptr \n " color=yellow style=filled]
1 [label="1: Start zero_ptr\nFormals: p:int *\nLocals: \n DECLARE_LOCALS(&return); [line 10]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,34 @@
/*
* 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.
*/
int fun_p(int *p) { return *p;}
int fun_v(int p) { return p;}
int fun_r(int &p) { return p;}
// cfgs should look similar for unbox_ref and unbox_ptr
// test conversions from int& to {int*, int, int&)
void unbox_ref() {
int a = 3;
int& r = a;
fun_p(&r);
fun_v(r);
fun_r(r);
}
// test conversions from int* to {int*, int, int&)
void unbox_ptr() {
int a = 3;
int *p = &a;
fun_p(p);
fun_v(*p);
fun_r(*p);
}

@ -0,0 +1,89 @@
digraph iCFG {
23 [label="23: DeclStmt \n *&a:int =3 [line 28]\n " shape="box"]
23 -> 22 ;
22 [label="22: DeclStmt \n *&p:int *=&a [line 29]\n " shape="box"]
22 -> 21 ;
21 [label="21: Call _fun_fun_p \n n$5=*&p:int * [line 31]\n n$6=_fun_fun_p(n$5:int *) [line 31]\n REMOVE_TEMPS(n$5,n$6); [line 31]\n " shape="box"]
21 -> 20 ;
20 [label="20: Call _fun_fun_v \n n$2=*&p:int * [line 32]\n n$3=*n$2:int [line 32]\n n$4=_fun_fun_v(n$3:int ) [line 32]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 32]\n " shape="box"]
20 -> 19 ;
19 [label="19: Call _fun_fun_r \n n$0=*&p:int * [line 33]\n n$1=_fun_fun_r(n$0:int ) [line 33]\n REMOVE_TEMPS(n$0,n$1); [line 33]\n NULLIFY(&p,false); [line 33]\n NULLIFY(&a,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"]
19 -> 18 ;
18 [label="18: Exit unbox_ptr \n " color=yellow style=filled]
17 [label="17: Start unbox_ptr\nFormals: \nLocals: p:int * a:int \n DECLARE_LOCALS(&return,&p,&a); [line 27]\n NULLIFY(&p,false); [line 27]\n " color=yellow style=filled]
17 -> 23 ;
16 [label="16: DeclStmt \n *&a:int =3 [line 18]\n " shape="box"]
16 -> 15 ;
15 [label="15: DeclStmt \n *&r:int =&a [line 19]\n " shape="box"]
15 -> 14 ;
14 [label="14: Call _fun_fun_p \n n$5=*&r:int & [line 21]\n n$6=_fun_fun_p(n$5:int *) [line 21]\n REMOVE_TEMPS(n$5,n$6); [line 21]\n " shape="box"]
14 -> 13 ;
13 [label="13: Call _fun_fun_v \n n$2=*&r:int & [line 22]\n n$3=*n$2:int [line 22]\n n$4=_fun_fun_v(n$3:int ) [line 22]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 22]\n " shape="box"]
13 -> 12 ;
12 [label="12: Call _fun_fun_r \n n$0=*&r:int & [line 23]\n n$1=_fun_fun_r(n$0:int ) [line 23]\n REMOVE_TEMPS(n$0,n$1); [line 23]\n NULLIFY(&r,false); [line 23]\n NULLIFY(&a,false); [line 23]\n APPLY_ABSTRACTION; [line 23]\n " shape="box"]
12 -> 11 ;
11 [label="11: Exit unbox_ref \n " color=yellow style=filled]
10 [label="10: Start unbox_ref\nFormals: \nLocals: r:int & a:int \n DECLARE_LOCALS(&return,&r,&a); [line 17]\n NULLIFY(&r,false); [line 17]\n " color=yellow style=filled]
10 -> 16 ;
9 [label="9: Return Stmt \n n$0=*&p:int & [line 12]\n n$1=*n$0:int [line 12]\n *&return:int =n$1 [line 12]\n REMOVE_TEMPS(n$0,n$1); [line 12]\n NULLIFY(&p,false); [line 12]\n APPLY_ABSTRACTION; [line 12]\n " shape="box"]
9 -> 8 ;
8 [label="8: Exit fun_r \n " color=yellow style=filled]
7 [label="7: Start fun_r\nFormals: p:int &\nLocals: \n DECLARE_LOCALS(&return); [line 12]\n " color=yellow style=filled]
7 -> 9 ;
6 [label="6: Return Stmt \n n$0=*&p:int [line 11]\n *&return:int =n$0 [line 11]\n REMOVE_TEMPS(n$0); [line 11]\n NULLIFY(&p,false); [line 11]\n APPLY_ABSTRACTION; [line 11]\n " shape="box"]
6 -> 5 ;
5 [label="5: Exit fun_v \n " color=yellow style=filled]
4 [label="4: Start fun_v\nFormals: p:int \nLocals: \n DECLARE_LOCALS(&return); [line 11]\n " color=yellow style=filled]
4 -> 6 ;
3 [label="3: Return Stmt \n n$0=*&p:int * [line 10]\n n$1=*n$0:int [line 10]\n *&return:int =n$1 [line 10]\n REMOVE_TEMPS(n$0,n$1); [line 10]\n NULLIFY(&p,false); [line 10]\n APPLY_ABSTRACTION; [line 10]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit fun_p \n " color=yellow style=filled]
1 [label="1: Start fun_p\nFormals: p:int *\nLocals: \n DECLARE_LOCALS(&return); [line 10]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,70 @@
/*
* 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.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferResults;
import utils.InferRunner;
public class ReferenceStructTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/frontend/reference/reference_struct_e2e.cpp";
private static ImmutableList<String> inferCmd;
public static final String DIVIDE_BY_ZERO = "DIVIDE_BY_ZERO";
@ClassRule
public static DebuggableTemporaryFolder folder =
new DebuggableTemporaryFolder();
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsOnDiv0MethodsErrorIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
String[] procedures = {
"method_div0_ptr",
"field_div0_ptr",
"get_global_ptr_div0_method",
"get_global_ptr_div0_field",
"method_div0_ref",
"field_div0_ref",
"get_global_ref_div0_method",
"get_global_ref_div0_field"
};
assertThat(
"Results should contain the expected divide by zero",
inferResults,
containsExactly(
DIVIDE_BY_ZERO,
FILE,
procedures
)
);
}
}

@ -0,0 +1,68 @@
/*
* 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.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferResults;
import utils.InferRunner;
public class ReferenceTypeTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/frontend/reference/reference_type_e2e.cpp";
private static ImmutableList<String> inferCmd;
public static final String DIVIDE_BY_ZERO = "DIVIDE_BY_ZERO";
@ClassRule
public static DebuggableTemporaryFolder folder =
new DebuggableTemporaryFolder();
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsOnDiv0MethodsErrorIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
String[] procedures = {
"ptr_div0",
"ptr_div0_function",
"ptr_div0_function_temp_var",
"ref_div0",
"ref_div0_function",
"ref_div0_function_temp_var"
};
assertThat(
"Results should contain the expected divide by zero",
inferResults,
containsExactly(
DIVIDE_BY_ZERO,
FILE,
procedures
)
);
}
}

@ -0,0 +1,73 @@
/*
* 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.
*/
package frontend.cpp;
import org.junit.Rule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.ClangFrontendUtils;
public class ReferenceTest {
String basePath = "infer/tests/codetoanalyze/cpp/frontend/reference/";
@Rule
public DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder();
void frontendTest(String fileRelative) throws InterruptedException, IOException, InferException {
ClangFrontendUtils.createAndCompareCppDotFiles(folder, basePath + fileRelative);
}
@Test
public void testBoxDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("box.cpp");
}
@Test
public void testUnboxDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("unbox.cpp");
}
@Test
public void testInitDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("init.cpp");
}
@Test
public void testMemberAccessDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("member_access.cpp");
}
@Test
public void testMemberAccessFromReturnDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("member_access_from_return.cpp");
}
@Test
public void testReferenceTypeE2EDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("reference_type_e2e.cpp");
}
@Test
public void testReferenceStructE2EDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("reference_struct_e2e.cpp");
}
}
Loading…
Cancel
Save