Use mangling in function parameters to encode its position

Summary:
When clang instantiates template function with argument pack, it will
give the same name to all parameters coming from the pack. To avoid
name collisions, always add index of argument's position to mangled part
of the variable.
Seemingly unrelated changes are to make existing tests pass (don't use
simple variable name where it matters)

Reviewed By: dulmarod

Differential Revision: D3503608

fbshipit-source-id: 794093a
master
Andrzej Kotulski 9 years ago committed by Facebook Github Bot 6
parent 1420cabac5
commit e46cddb52b

@ -308,13 +308,13 @@ let translate_dispatch_function stmt_info stmt_list n =
| _ -> assert false
(* Create declaration statement: tp vname = iexp *)
let make_DeclStmt stmt_info di tp vname iexp =
let make_DeclStmt stmt_info di tp vname old_vdi iexp =
let init_expr_opt, init_expr_l = match iexp with
| Some iexp' ->
let ie = create_implicit_cast_expr stmt_info [iexp'] tp `IntegralCast in
Some ie, [ie]
| None -> None, [] in
let var_decl_info = { empty_var_decl_info with Clang_ast_t.vdi_init_expr = init_expr_opt } in
let var_decl_info = { old_vdi with Clang_ast_t.vdi_init_expr = init_expr_opt } in
let di = fresh_decl_info di in
let var_decl = Clang_ast_t.VarDecl (di, vname, tp, var_decl_info) in
Clang_ast_t.DeclStmt (stmt_info, init_expr_l, [var_decl])
@ -393,16 +393,18 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let build_idx_decl pidx =
match pidx with
| Clang_ast_t.ParmVarDecl (di_idx, name_idx, tp_idx, _) ->
| Clang_ast_t.ParmVarDecl (di_idx, name_idx, tp_idx, vdi) ->
let zero = create_integer_literal "0" in
(* tp_idx idx = 0; *)
let idx_decl_stmt = make_DeclStmt (fresh_stmt_info stmt_info) di_idx tp_idx name_idx (Some zero) in
let idx_decl_stmt = make_DeclStmt (fresh_stmt_info stmt_info) di_idx tp_idx
name_idx vdi (Some zero) in
let idx_ei = make_expr_info tp_idx in
let pointer = di_idx.Clang_ast_t.di_pointer in
let idx_decl_ref = make_decl_ref_tp `Var pointer name_idx false tp_idx in
let idx_drei = make_decl_ref_expr_info idx_decl_ref in
let idx_decl_ref_exp = make_decl_ref_exp stmt_info idx_ei idx_drei in
let idx_cast = create_implicit_cast_expr (fresh_stmt_info stmt_info) [idx_decl_ref_exp] tp_idx `LValueToRValue in
let idx_cast = create_implicit_cast_expr (fresh_stmt_info stmt_info) [idx_decl_ref_exp]
tp_idx `LValueToRValue in
idx_decl_stmt, idx_decl_ref_exp, idx_cast, tp_idx
| _ -> assert false in
@ -415,7 +417,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
(* build statement BOOL *stop = malloc(sizeof(BOOL)); *)
let build_stop pstop =
match pstop with
| Clang_ast_t.ParmVarDecl (di, name, tp, _) ->
| Clang_ast_t.ParmVarDecl (di, name, tp, vdi) ->
let tp_fun = create_void_unsigned_long_type in
let type_opt = Some create_BOOL_type in
let parameter = Clang_ast_t.UnaryExprOrTypeTraitExpr
@ -427,7 +429,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let malloc_name = Ast_utils.make_name_decl CFrontend_config.malloc in
let malloc = create_call stmt_info pointer malloc_name tp_fun [parameter] in
let init_exp = create_implicit_cast_expr (fresh_stmt_info stmt_info) [malloc] tp `BitCast in
make_DeclStmt (fresh_stmt_info stmt_info) di tp name (Some init_exp)
make_DeclStmt (fresh_stmt_info stmt_info) di tp name vdi (Some init_exp)
| _ -> assert false in
(* BOOL *stop =NO; *)
@ -588,7 +590,7 @@ let trans_negation_with_conditional stmt_info expr_info stmt_list =
let create_assume_not_null_call decl_info var_name var_type =
let stmt_info = stmt_info_with_fresh_pointer (make_stmt_info decl_info) in
let boi = { Clang_ast_t.boi_kind = `NE } in
let decl_ptr = Ast_utils.get_invalid_pointer () in
let decl_ptr = decl_info.Clang_ast_t.di_pointer in
let decl_ref = make_decl_ref_tp `Var decl_ptr var_name false var_type in
let stmt_info_var = dummy_stmt_info () in
let decl_ref_info = make_decl_ref_expr_info decl_ref in

@ -618,19 +618,24 @@ struct
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name type_name_crc)
let get_var_name_string name_info var_decl_info =
let get_var_name_mangled name_info var_decl_info =
let clang_name = Ast_utils.get_qualified_name name_info in
match clang_name, var_decl_info.Clang_ast_t.vdi_parm_index_in_function with
| "", Some index -> "__param_" ^ string_of_int index
| "", None -> assert false
| _ -> clang_name
let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in
let name_string =
match clang_name, param_idx_opt with
| "", Some index -> "__param_" ^ string_of_int index
| "", None -> assert false
| _ -> clang_name in
let mangled = match param_idx_opt with
| Some index -> Mangled.mangled name_string (string_of_int index)
| None -> Mangled.from_string name_string in
name_string, mangled
let mk_sil_var name decl_info_type_ptr_opt procname outer_procname =
let name_string = Ast_utils.get_qualified_name name in
match decl_info_type_ptr_opt with
| Some (decl_info, type_ptr, var_decl_info, should_be_mangled) ->
let name_string = get_var_name_string name var_decl_info in
let simple_name = Mangled.from_string name_string in
let name_string, simple_name = get_var_name_mangled name var_decl_info in
if var_decl_info.Clang_ast_t.vdi_is_global then
let global_mangled_name =
if var_decl_info.Clang_ast_t.vdi_is_static_local then

@ -206,7 +206,8 @@ sig
val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname
val get_var_name_string : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> string
val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info ->
(string * Mangled.t)
val mk_sil_var : Clang_ast_t.named_decl_info -> var_info option -> Procname.t -> Procname.t ->
Pvar.t

@ -14,7 +14,7 @@ open! Utils
type method_signature = {
mutable name : Procname.t;
args : (string * Clang_ast_t.type_ptr) list;
args : (Mangled.t * Clang_ast_t.type_ptr) list;
ret_type : Clang_ast_t.type_ptr;
attributes : Clang_ast_t.attribute list;
loc : Clang_ast_t.source_range;
@ -99,7 +99,7 @@ let replace_name_ms ms name =
let ms_to_string ms =
"Method " ^ (Procname.to_string ms.name) ^ " " ^
IList.to_string
(fun (s1, s2) -> s1 ^ ", " ^ (Clang_ast_j.string_of_type_ptr s2))
(fun (s1, s2) -> (Mangled.to_string s1) ^ ", " ^ (Clang_ast_j.string_of_type_ptr s2))
ms.args
^ "->" ^ (Clang_ast_j.string_of_type_ptr ms.ret_type) ^ " " ^
Clang_ast_j.string_of_source_range ms.loc

@ -19,7 +19,7 @@ val ms_get_name : method_signature -> Procname.t
val ms_set_name : method_signature -> Procname.t -> unit
val ms_get_args : method_signature ->
(string * Clang_ast_t.type_ptr) list
(Mangled.t * Clang_ast_t.type_ptr) list
val ms_get_ret_type : method_signature -> Clang_ast_t.type_ptr
@ -43,7 +43,7 @@ val ms_is_getter : method_signature -> bool
val ms_is_setter : method_signature -> bool
val make_ms : Procname.t -> (string * Clang_ast_t.type_ptr) list -> Clang_ast_t.type_ptr
val make_ms : Procname.t -> (Mangled.t * Clang_ast_t.type_ptr) list -> Clang_ast_t.type_ptr
-> Clang_ast_t.attribute list -> Clang_ast_t.source_range -> bool -> ?is_cpp_virtual:bool
-> Config.clang_lang -> Clang_ast_t.pointer option -> Clang_ast_t.pointer option
-> Typ.t option -> method_signature

@ -54,10 +54,10 @@ let get_class_param function_method_decl_info =
match function_method_decl_info with
| Cpp_Meth_decl_info (_, _, class_name, _) ->
let class_type = Ast_expressions.create_class_type (class_name, `CPP) in
[(CFrontend_config.this, class_type)]
[(Mangled.from_string CFrontend_config.this, class_type)]
| ObjC_Meth_decl_info (_, class_name) ->
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
[(CFrontend_config.self, class_type)]
[(Mangled.from_string CFrontend_config.self, class_type)]
| _ -> []
else []
@ -77,7 +77,8 @@ let get_return_param tenv function_method_decl_info =
let return_type_ptr = get_original_return_type function_method_decl_info in
let return_typ = CTypes_decl.type_ptr_to_sil_type tenv return_type_ptr in
if should_add_return_param return_typ ~is_objc_method then
[(CFrontend_config.return_param, Ast_expressions.create_pointer_type return_type_ptr)]
[(Mangled.from_string CFrontend_config.return_param,
Ast_expressions.create_pointer_type return_type_ptr)]
else
[]
@ -109,13 +110,13 @@ let get_parameters tenv function_method_decl_info =
let par_to_ms_par par =
match par with
| Clang_ast_t.ParmVarDecl (_, name_info, type_ptr, var_decl_info) ->
let name = General_utils.get_var_name_string name_info var_decl_info in
let _, mangled = General_utils.get_var_name_mangled name_info var_decl_info in
let param_typ = CTypes_decl.type_ptr_to_sil_type tenv type_ptr in
let type_ptr' = match param_typ with
| Typ.Tstruct _ when General_utils.is_cpp_translation Config.clang_lang ->
Ast_expressions.create_reference_type type_ptr
| _ -> type_ptr in
(name, type_ptr')
(mangled, type_ptr')
| _ -> assert false in
let pars = IList.map par_to_ms_par (get_param_decls function_method_decl_info) in
get_class_param function_method_decl_info @ pars @ get_return_param tenv function_method_decl_info
@ -303,18 +304,18 @@ let get_formal_parameters tenv ms =
let rec defined_parameters pl =
match pl with
| [] -> []
| (name, raw_type):: pl' ->
| (mangled, raw_type):: pl' ->
let should_add_pointer name ms =
let is_objc_self = name = CFrontend_config.self &&
CMethod_signature.ms_get_lang ms = Config.OBJC in
let is_cxx_this = name = CFrontend_config.this &&
CMethod_signature.ms_get_lang ms = 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
let tp = if should_add_pointer (Mangled.to_string mangled) 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
(Mangled.from_string name, typ):: defined_parameters pl' in
(mangled, typ):: defined_parameters pl' in
defined_parameters (CMethod_signature.ms_get_args ms)
let get_return_type tenv ms =
@ -348,7 +349,8 @@ let sil_method_annotation_of_args args : Typ.method_annotation =
let mk_annot param_name annot_name =
let annot = { Typ.class_name = annot_name; Typ.parameters = [param_name]; } in
annot, default_visibility in
let arg_to_sil_annot (arg_name, type_ptr) acc =
let arg_to_sil_annot (arg_mangled, type_ptr) acc =
let arg_name = Mangled.to_string arg_mangled in
if CFrontend_utils.Ast_utils.is_type_nullable type_ptr then
[mk_annot arg_name Annotations.nullable] :: acc
else Typ.item_annotation_empty::acc in

@ -143,8 +143,9 @@ let get_predefined_ms_stringWithUTF8String class_name method_name mk_procname la
class_name = CFrontend_config.nsstring_cl
&& method_name = CFrontend_config.string_with_utf8_m in
let id_type = Ast_expressions.create_id_type in
let args = [(Mangled.from_string "x", Ast_expressions.create_char_star_type)] in
get_predefined_ms_method condition class_name method_name Procname.Class_objc_method
mk_procname lang [("x", Ast_expressions.create_char_star_type)] id_type [] None
mk_procname lang args id_type [] None
let get_predefined_ms_retain_release method_name mk_procname lang =
let condition = is_retain_or_release method_name in
@ -153,7 +154,7 @@ let get_predefined_ms_retain_release method_name mk_procname lang =
then Ast_expressions.create_id_type else Ast_expressions.create_void_type in
let class_name = CFrontend_config.nsobject_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
let args = [(CFrontend_config.self, class_type)] in
let args = [(Mangled.from_string CFrontend_config.self, class_type)] in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname lang args return_type [] (get_builtinname method_name)
@ -163,7 +164,7 @@ let get_predefined_ms_autoreleasepool_init class_name method_name mk_procname la
&& class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname lang [(CFrontend_config.self, class_type)]
mk_procname lang [(Mangled.from_string CFrontend_config.self, class_type)]
Ast_expressions.create_void_type [] None
let get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procname lang =
@ -171,15 +172,17 @@ let get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procna
(method_name = CFrontend_config.release || method_name = CFrontend_config.drain)
&& class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
let args = [(Mangled.from_string CFrontend_config.self, class_type)] in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname lang [(CFrontend_config.self, class_type)] Ast_expressions.create_void_type
mk_procname lang args Ast_expressions.create_void_type
[] (Some ModelBuiltins.__objc_release_autorelease_pool)
let get_predefined_ms_is_kind_of_class class_name method_name mk_procname lang =
let condition = method_name = CFrontend_config.is_kind_of_class in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in
let args = [(Mangled.from_string CFrontend_config.self, class_type)] in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname lang [(CFrontend_config.self, class_type)] Ast_expressions.create_BOOL_type
mk_procname lang args Ast_expressions.create_BOOL_type
[] (Some ModelBuiltins.__instanceof)
let get_predefined_model_method_signature class_name method_name mk_procname lang =

@ -0,0 +1,26 @@
/*
* Copyright (c) 2016 - 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.
*/
// div(a,b,c,d) = 1/a + 1/b + 1/c + 1/d;
int div(int d) { return 1 / d; }
template <typename... Args>
int div(int v, Args... args) {
return 1 / v + div(args...);
}
int div0_1arg() { return div(0); }
int div0_3args1() { return div(0, 2, 3); }
int div0_3args2() { return div(1, 0, 3); }
int div0_3args3() { return div(1, 2, 0); }
int div0_3args4() { return div(1, 0, 0); }
int div0_10args() { return div(1, 2, 3, 4, 5, 6, 7, 0, 9, 10); }
int no_div0_3_args() { return div(1, 2, 3); }
int no_div0_10args() { return div(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); }

@ -0,0 +1,201 @@
/* @generated */
digraph iCFG {
54 [label="54: Return Stmt \n n$0=_fun_div<5ae447456b906d06>(1:int ,2:int ,3:int ,4:int ,5:int ,6:int ,7:int ,8:int ,9:int ,10:int ) [line 26]\n *&return:int =n$0 [line 26]\n " shape="box"]
54 -> 53 ;
53 [label="53: Exit no_div0_10args \n " color=yellow style=filled]
52 [label="52: Start no_div0_10args\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 26]\n " color=yellow style=filled]
52 -> 54 ;
51 [label="51: Return Stmt \n n$0=_fun_div<int, int>(1:int ,2:int ,3:int ) [line 25]\n *&return:int =n$0 [line 25]\n " shape="box"]
51 -> 50 ;
50 [label="50: Exit no_div0_3_args \n " color=yellow style=filled]
49 [label="49: Start no_div0_3_args\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n " color=yellow style=filled]
49 -> 51 ;
48 [label="48: Return Stmt \n n$0=_fun_div<5ae447456b906d06>(1:int ,2:int ,3:int ,4:int ,5:int ,6:int ,7:int ,0:int ,9:int ,10:int ) [line 23]\n *&return:int =n$0 [line 23]\n " shape="box"]
48 -> 47 ;
47 [label="47: Exit div0_10args \n " color=yellow style=filled]
46 [label="46: Start div0_10args\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 23]\n " color=yellow style=filled]
46 -> 48 ;
45 [label="45: Return Stmt \n n$0=_fun_div<int, int>(1:int ,0:int ,0:int ) [line 22]\n *&return:int =n$0 [line 22]\n " shape="box"]
45 -> 44 ;
44 [label="44: Exit div0_3args4 \n " color=yellow style=filled]
43 [label="43: Start div0_3args4\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 22]\n " color=yellow style=filled]
43 -> 45 ;
42 [label="42: Return Stmt \n n$0=_fun_div<int, int>(1:int ,2:int ,0:int ) [line 21]\n *&return:int =n$0 [line 21]\n " shape="box"]
42 -> 41 ;
41 [label="41: Exit div0_3args3 \n " color=yellow style=filled]
40 [label="40: Start div0_3args3\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 21]\n " color=yellow style=filled]
40 -> 42 ;
39 [label="39: Return Stmt \n n$0=_fun_div<int, int>(1:int ,0:int ,3:int ) [line 20]\n *&return:int =n$0 [line 20]\n " shape="box"]
39 -> 38 ;
38 [label="38: Exit div0_3args2 \n " color=yellow style=filled]
37 [label="37: Start div0_3args2\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 20]\n " color=yellow style=filled]
37 -> 39 ;
36 [label="36: Return Stmt \n n$0=_fun_div<int, int>(0:int ,2:int ,3:int ) [line 19]\n *&return:int =n$0 [line 19]\n " shape="box"]
36 -> 35 ;
35 [label="35: Exit div0_3args1 \n " color=yellow style=filled]
34 [label="34: Start div0_3args1\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 19]\n " color=yellow style=filled]
34 -> 36 ;
33 [label="33: Return Stmt \n n$0=_fun_div(0:int ) [line 17]\n *&return:int =n$0 [line 17]\n " shape="box"]
33 -> 32 ;
32 [label="32: Exit div0_1arg \n " color=yellow style=filled]
31 [label="31: Start div0_1arg\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 17]\n " color=yellow style=filled]
31 -> 33 ;
30 [label="30: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=*&args:int [line 14]\n n$5=*&args:int [line 14]\n n$6=*&args:int [line 14]\n n$7=*&args:int [line 14]\n n$8=*&args:int [line 14]\n n$9=*&args:int [line 14]\n n$10=_fun_div<int, int, int, int, int, int, int, int>(n$1:int ,n$2:int ,n$3:int ,n$4:int ,n$5:int ,n$6:int ,n$7:int ,n$8:int ,n$9:int ) [line 14]\n *&return:int =((1 / n$0) + n$10) [line 14]\n " shape="box"]
30 -> 11 ;
29 [label="29: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=*&args:int [line 14]\n n$5=*&args:int [line 14]\n n$6=*&args:int [line 14]\n n$7=*&args:int [line 14]\n n$8=*&args:int [line 14]\n n$9=_fun_div<int, int, int, int, int, int, int>(n$1:int ,n$2:int ,n$3:int ,n$4:int ,n$5:int ,n$6:int ,n$7:int ,n$8:int ) [line 14]\n *&return:int =((1 / n$0) + n$9) [line 14]\n " shape="box"]
29 -> 13 ;
28 [label="28: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=*&args:int [line 14]\n n$5=*&args:int [line 14]\n n$6=*&args:int [line 14]\n n$7=*&args:int [line 14]\n n$8=_fun_div<int, int, int, int, int, int>(n$1:int ,n$2:int ,n$3:int ,n$4:int ,n$5:int ,n$6:int ,n$7:int ) [line 14]\n *&return:int =((1 / n$0) + n$8) [line 14]\n " shape="box"]
28 -> 15 ;
27 [label="27: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=*&args:int [line 14]\n n$5=*&args:int [line 14]\n n$6=*&args:int [line 14]\n n$7=_fun_div<int, int, int, int, int>(n$1:int ,n$2:int ,n$3:int ,n$4:int ,n$5:int ,n$6:int ) [line 14]\n *&return:int =((1 / n$0) + n$7) [line 14]\n " shape="box"]
27 -> 17 ;
26 [label="26: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=*&args:int [line 14]\n n$5=*&args:int [line 14]\n n$6=_fun_div<int, int, int, int>(n$1:int ,n$2:int ,n$3:int ,n$4:int ,n$5:int ) [line 14]\n *&return:int =((1 / n$0) + n$6) [line 14]\n " shape="box"]
26 -> 19 ;
25 [label="25: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=*&args:int [line 14]\n n$5=_fun_div<int, int, int>(n$1:int ,n$2:int ,n$3:int ,n$4:int ) [line 14]\n *&return:int =((1 / n$0) + n$5) [line 14]\n " shape="box"]
25 -> 21 ;
24 [label="24: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=*&args:int [line 14]\n n$4=_fun_div<int, int>(n$1:int ,n$2:int ,n$3:int ) [line 14]\n *&return:int =((1 / n$0) + n$4) [line 14]\n " shape="box"]
24 -> 23 ;
23 [label="23: Exit div<int, int, int> \n " color=yellow style=filled]
22 [label="22: Start div<int, int, int>\nFormals: v:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
22 -> 24 ;
21 [label="21: Exit div<int, int, int, int> \n " color=yellow style=filled]
20 [label="20: Start div<int, int, int, int>\nFormals: v:int args:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
20 -> 25 ;
19 [label="19: Exit div<int, int, int, int, int> \n " color=yellow style=filled]
18 [label="18: Start div<int, int, int, int, int>\nFormals: v:int args:int args:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
18 -> 26 ;
17 [label="17: Exit div<int, int, int, int, int, int> \n " color=yellow style=filled]
16 [label="16: Start div<int, int, int, int, int, int>\nFormals: v:int args:int args:int args:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
16 -> 27 ;
15 [label="15: Exit div<int, int, int, int, int, int, int> \n " color=yellow style=filled]
14 [label="14: Start div<int, int, int, int, int, int, int>\nFormals: v:int args:int args:int args:int args:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
14 -> 28 ;
13 [label="13: Exit div<int, int, int, int, int, int, int, int> \n " color=yellow style=filled]
12 [label="12: Start div<int, int, int, int, int, int, int, int>\nFormals: v:int args:int args:int args:int args:int args:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
12 -> 29 ;
11 [label="11: Exit div<5ae447456b906d06> \n " color=yellow style=filled]
10 [label="10: Start div<5ae447456b906d06>\nFormals: v:int args:int args:int args:int args:int args:int args:int args:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
10 -> 30 ;
9 [label="9: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=*&args:int [line 14]\n n$3=_fun_div<int>(n$1:int ,n$2:int ) [line 14]\n *&return:int =((1 / n$0) + n$3) [line 14]\n " shape="box"]
9 -> 5 ;
8 [label="8: Return Stmt \n n$0=*&v:int [line 14]\n n$1=*&args:int [line 14]\n n$2=_fun_div(n$1:int ) [line 14]\n *&return:int =((1 / n$0) + n$2) [line 14]\n " shape="box"]
8 -> 7 ;
7 [label="7: Exit div<int> \n " color=yellow style=filled]
6 [label="6: Start div<int>\nFormals: v:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
6 -> 8 ;
5 [label="5: Exit div<int, int> \n " color=yellow style=filled]
4 [label="4: Start div<int, int>\nFormals: v:int args:int args:int \nLocals: \n DECLARE_LOCALS(&return); [line 13]\n " color=yellow style=filled]
4 -> 9 ;
3 [label="3: Return Stmt \n n$0=*&d:int [line 11]\n *&return:int =(1 / n$0) [line 11]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit div \n " color=yellow style=filled]
1 [label="1: Start div\nFormals: d:int \nLocals: \n DECLARE_LOCALS(&return); [line 11]\n " color=yellow style=filled]
1 -> 3 ;
}

@ -0,0 +1,68 @@
/*
* Copyright (c) 2016 - 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 TemplateFunctionPackTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/frontend/templates/function_pack.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 = {
"div0_1arg",
"div0_3args1",
"div0_3args2",
"div0_3args3",
"div0_3args4",
"div0_10args",
};
assertThat(
"Results should contain the expected divide by zero",
inferResults,
containsExactly(
DIVIDE_BY_ZERO,
FILE,
procedures
)
);
}
}

@ -58,4 +58,11 @@ public class TemplatesTest {
throws InterruptedException, IOException, InferException {
frontendTest("sizeof_pack.cpp");
}
@Test
public void testFunctionPackDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("function_pack.cpp");
}
}

Loading…
Cancel
Save