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 | _ -> assert false
(* Create declaration statement: tp vname = iexp *) (* 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 let init_expr_opt, init_expr_l = match iexp with
| Some iexp' -> | Some iexp' ->
let ie = create_implicit_cast_expr stmt_info [iexp'] tp `IntegralCast in let ie = create_implicit_cast_expr stmt_info [iexp'] tp `IntegralCast in
Some ie, [ie] Some ie, [ie]
| None -> None, [] in | 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 di = fresh_decl_info di in
let var_decl = Clang_ast_t.VarDecl (di, vname, tp, var_decl_info) 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]) 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 = let build_idx_decl pidx =
match pidx with 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 let zero = create_integer_literal "0" in
(* tp_idx idx = 0; *) (* 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 idx_ei = make_expr_info tp_idx in
let pointer = di_idx.Clang_ast_t.di_pointer 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_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_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_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 idx_decl_stmt, idx_decl_ref_exp, idx_cast, tp_idx
| _ -> assert false in | _ -> 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)); *) (* build statement BOOL *stop = malloc(sizeof(BOOL)); *)
let build_stop pstop = let build_stop pstop =
match pstop with 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 tp_fun = create_void_unsigned_long_type in
let type_opt = Some create_BOOL_type in let type_opt = Some create_BOOL_type in
let parameter = Clang_ast_t.UnaryExprOrTypeTraitExpr 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_name = Ast_utils.make_name_decl CFrontend_config.malloc in
let malloc = create_call stmt_info pointer malloc_name tp_fun [parameter] 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 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 | _ -> assert false in
(* BOOL *stop =NO; *) (* 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 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 stmt_info = stmt_info_with_fresh_pointer (make_stmt_info decl_info) in
let boi = { Clang_ast_t.boi_kind = `NE } 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 decl_ref = make_decl_ref_tp `Var decl_ptr var_name false var_type in
let stmt_info_var = dummy_stmt_info () in let stmt_info_var = dummy_stmt_info () in
let decl_ref_info = make_decl_ref_expr_info decl_ref in let decl_ref_info = make_decl_ref_expr_info decl_ref in

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

@ -14,7 +14,7 @@ open! Utils
type method_signature = { type method_signature = {
mutable name : Procname.t; 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; ret_type : Clang_ast_t.type_ptr;
attributes : Clang_ast_t.attribute list; attributes : Clang_ast_t.attribute list;
loc : Clang_ast_t.source_range; loc : Clang_ast_t.source_range;
@ -99,7 +99,7 @@ let replace_name_ms ms name =
let ms_to_string ms = let ms_to_string ms =
"Method " ^ (Procname.to_string ms.name) ^ " " ^ "Method " ^ (Procname.to_string ms.name) ^ " " ^
IList.to_string 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 ms.args
^ "->" ^ (Clang_ast_j.string_of_type_ptr ms.ret_type) ^ " " ^ ^ "->" ^ (Clang_ast_j.string_of_type_ptr ms.ret_type) ^ " " ^
Clang_ast_j.string_of_source_range ms.loc 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_set_name : method_signature -> Procname.t -> unit
val ms_get_args : method_signature -> 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 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 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 -> 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 -> Config.clang_lang -> Clang_ast_t.pointer option -> Clang_ast_t.pointer option
-> Typ.t option -> method_signature -> Typ.t option -> method_signature

@ -54,10 +54,10 @@ let get_class_param function_method_decl_info =
match function_method_decl_info with match function_method_decl_info with
| Cpp_Meth_decl_info (_, _, class_name, _) -> | Cpp_Meth_decl_info (_, _, class_name, _) ->
let class_type = Ast_expressions.create_class_type (class_name, `CPP) in 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) -> | ObjC_Meth_decl_info (_, class_name) ->
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in 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 [] 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_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 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 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 else
[] []
@ -109,13 +110,13 @@ let get_parameters tenv function_method_decl_info =
let par_to_ms_par par = let par_to_ms_par par =
match par with match par with
| Clang_ast_t.ParmVarDecl (_, name_info, type_ptr, var_decl_info) -> | 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 param_typ = CTypes_decl.type_ptr_to_sil_type tenv type_ptr in
let type_ptr' = match param_typ with let type_ptr' = match param_typ with
| Typ.Tstruct _ when General_utils.is_cpp_translation Config.clang_lang -> | Typ.Tstruct _ when General_utils.is_cpp_translation Config.clang_lang ->
Ast_expressions.create_reference_type type_ptr Ast_expressions.create_reference_type type_ptr
| _ -> type_ptr in | _ -> type_ptr in
(name, type_ptr') (mangled, type_ptr')
| _ -> assert false in | _ -> assert false in
let pars = IList.map par_to_ms_par (get_param_decls function_method_decl_info) 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 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 = let rec defined_parameters pl =
match pl with match pl with
| [] -> [] | [] -> []
| (name, raw_type):: pl' -> | (mangled, raw_type):: pl' ->
let should_add_pointer name ms = let should_add_pointer name ms =
let is_objc_self = name = CFrontend_config.self && let is_objc_self = name = CFrontend_config.self &&
CMethod_signature.ms_get_lang ms = Config.OBJC in CMethod_signature.ms_get_lang ms = Config.OBJC in
let is_cxx_this = name = CFrontend_config.this && let is_cxx_this = name = CFrontend_config.this &&
CMethod_signature.ms_get_lang ms = Config.CPP in CMethod_signature.ms_get_lang ms = Config.CPP in
(is_objc_self && CMethod_signature.ms_is_instance ms) || is_cxx_this 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) (Ast_expressions.create_pointer_type raw_type)
else raw_type in else raw_type in
let typ = CTypes_decl.type_ptr_to_sil_type tenv tp 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) defined_parameters (CMethod_signature.ms_get_args ms)
let get_return_type tenv 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 mk_annot param_name annot_name =
let annot = { Typ.class_name = annot_name; Typ.parameters = [param_name]; } in let annot = { Typ.class_name = annot_name; Typ.parameters = [param_name]; } in
annot, default_visibility 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 if CFrontend_utils.Ast_utils.is_type_nullable type_ptr then
[mk_annot arg_name Annotations.nullable] :: acc [mk_annot arg_name Annotations.nullable] :: acc
else Typ.item_annotation_empty::acc in 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 class_name = CFrontend_config.nsstring_cl
&& method_name = CFrontend_config.string_with_utf8_m in && method_name = CFrontend_config.string_with_utf8_m in
let id_type = Ast_expressions.create_id_type 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 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 get_predefined_ms_retain_release method_name mk_procname lang =
let condition = is_retain_or_release method_name in 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 then Ast_expressions.create_id_type else Ast_expressions.create_void_type in
let class_name = CFrontend_config.nsobject_cl in let class_name = CFrontend_config.nsobject_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) 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 get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname lang args return_type [] (get_builtinname method_name) 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 && class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) 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 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 Ast_expressions.create_void_type [] None
let get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procname lang = 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) (method_name = CFrontend_config.release || method_name = CFrontend_config.drain)
&& class_name = CFrontend_config.nsautorelease_pool_cl in && class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) 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 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) [] (Some ModelBuiltins.__objc_release_autorelease_pool)
let get_predefined_ms_is_kind_of_class class_name method_name mk_procname lang = 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 condition = method_name = CFrontend_config.is_kind_of_class in
let class_type = Ast_expressions.create_class_type (class_name, `OBJC) 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 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) [] (Some ModelBuiltins.__instanceof)
let get_predefined_model_method_signature class_name method_name mk_procname lang = 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 { throws InterruptedException, IOException, InferException {
frontendTest("sizeof_pack.cpp"); frontendTest("sizeof_pack.cpp");
} }
@Test
public void testFunctionPackDotFilesMatch()
throws InterruptedException, IOException, InferException {
frontendTest("function_pack.cpp");
}
} }

Loading…
Cancel
Save