diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 74bc6ff72..ca8fa29b4 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -2062,6 +2062,30 @@ struct "CXXTypeidExpr" stmt_info all_res_trans in { res_trans_to_parent with exps = res_trans_call.exps } + and cxxStdInitializerListExpr_trans trans_state stmt_info stmts expr_info = + let context = trans_state.context in + let tenv = context.CContext.tenv in + let sil_loc = CLocation.get_sil_location stmt_info trans_state.context in + let type_pointer = expr_info.Clang_ast_t.ei_type_ptr in + let typ = CTypes_decl.type_ptr_to_sil_type tenv type_pointer in + let fun_name = Procname.from_string_c_fun CFrontend_config.infer_skip_fun in + let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in + let trans_state_param = { trans_state_pri with succ_nodes = [] } in + let res_trans_subexpr_list = IList.map (instruction trans_state_param) stmts in + let params = collect_exprs res_trans_subexpr_list in + let sil_fun = Sil.Const (Sil.Cfun fun_name) in + let ret_id = Ident.create_fresh Ident.knormal in + let ret_exp = Sil.Var ret_id in + let call_instr = Sil.Call ([ret_id], sil_fun, params, sil_loc, Sil.cf_default) in + let res_trans_call = { empty_res_trans with + ids = [ret_id]; + instrs = [call_instr]; + exps = [(ret_exp, typ)]; } in + let all_res_trans = res_trans_subexpr_list @ [res_trans_call] in + let res_trans_to_parent = PriorityNode.compute_results_to_parent trans_state_pri sil_loc + "CXXStdInitializerListExpr" stmt_info all_res_trans in + { res_trans_to_parent with exps = res_trans_call.exps } + (* Translates a clang instruction into SIL instructions. It takes a *) (* a trans_state containing current info on the translation and it returns *) (* a result_state.*) @@ -2333,6 +2357,9 @@ struct | CXXTypeidExpr (stmt_info, stmts, expr_info) -> cxxTypeidExpr_trans trans_state stmt_info stmts expr_info + | CXXStdInitializerListExpr (stmt_info, stmts, expr_info) -> + cxxStdInitializerListExpr_trans trans_state stmt_info stmts expr_info + | s -> (Printing.log_stats "\n!!!!WARNING: found statement %s. \nACTION REQUIRED: Translation need to be defined. Statement ignored.... \n" (Ast_utils.string_of_stmt s); diff --git a/infer/tests/codetoanalyze/cpp/frontend/constructors/std_init_list.cpp b/infer/tests/codetoanalyze/cpp/frontend/constructors/std_init_list.cpp new file mode 100644 index 000000000..777c38183 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/constructors/std_init_list.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#include + +class X { + public: + X(std::initializer_list list) { + for (auto i = list.begin(); i != list.end(); i++) { + sum = sum + i; + } + } + + private: + int sum; +}; + +int main() { X x = {1, 2, 3, 4, 5}; } diff --git a/infer/tests/codetoanalyze/cpp/frontend/constructors/std_init_list.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/constructors/std_init_list.cpp.dot new file mode 100644 index 000000000..ee8415895 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/constructors/std_init_list.cpp.dot @@ -0,0 +1,45 @@ +digraph iCFG { +11 [label="11: DeclStmt \n *&SIL_materialize_temp__n$0[0]:int =1 [line 24]\n *&SIL_materialize_temp__n$0[1]:int =2 [line 24]\n *&SIL_materialize_temp__n$0[2]:int =3 [line 24]\n *&SIL_materialize_temp__n$0[3]:int =4 [line 24]\n *&SIL_materialize_temp__n$0[4]:int =5 [line 24]\n n$1=_fun___infer_skip_function(&SIL_materialize_temp__n$0:int [5]) [line 24]\n _fun_X_X(&x:class X *,n$1:class std::initializer_list ) [line 24]\n REMOVE_TEMPS(n$1); [line 24]\n NULLIFY(&SIL_materialize_temp__n$0,false); [line 24]\n NULLIFY(&x,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] + + + 11 -> 10 ; +10 [label="10: Exit main \n " color=yellow style=filled] + + +9 [label="9: Start main\nFormals: \nLocals: x:class X SIL_materialize_temp__n$0:int [5] \n DECLARE_LOCALS(&return,&x,&SIL_materialize_temp__n$0); [line 24]\n " color=yellow style=filled] + + + 9 -> 11 ; +8 [label="8: Prune (false branch) \n PRUNE(((n$3 != n$5) == 0), false); [line 15]\n REMOVE_TEMPS(n$3,n$4,n$5); [line 15]\n NULLIFY(&i,false); [line 15]\n NULLIFY(&list,false); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"] + + + 8 -> 2 ; +7 [label="7: Prune (true branch) \n PRUNE(((n$3 != n$5) != 0), true); [line 15]\n REMOVE_TEMPS(n$3,n$4,n$5); [line 15]\n " shape="invhouse"] + + + 7 -> 5 ; +6 [label="6: BinaryOperatorStmt: NE \n n$3=*&i:int * [line 15]\n n$4=*&list:class std::initializer_list [line 15]\n n$5=_fun_std::initializer_list_end(&list:class std::initializer_list &) [line 15]\n " shape="box"] + + + 6 -> 7 ; + 6 -> 8 ; +5 [label="5: UnaryOperator \n n$2=*&i:int * [line 15]\n *&i:int *=(n$2 + 1) [line 15]\n REMOVE_TEMPS(n$2); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] + + + 5 -> 3 ; +4 [label="4: DeclStmt \n n$0=*&list:class std::initializer_list [line 15]\n n$1=_fun_std::initializer_list_begin(&list:class std::initializer_list &) [line 15]\n *&i:int *=n$1 [line 15]\n REMOVE_TEMPS(n$0,n$1); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] + + + 4 -> 3 ; +3 [label="3: + \n " ] + + + 3 -> 6 ; +2 [label="2: Exit X_X \n " color=yellow style=filled] + + +1 [label="1: Start X_X\nFormals: this:class X * list:class std::initializer_list \nLocals: i:int * \n DECLARE_LOCALS(&return,&i); [line 14]\n NULLIFY(&i,false); [line 14]\n NULLIFY(&this,false); [line 14]\n " color=yellow style=filled] + + + 1 -> 4 ; +} diff --git a/infer/tests/frontend/cpp/ConstructorsTest.java b/infer/tests/frontend/cpp/ConstructorsTest.java index 0beaf02b6..d56812672 100644 --- a/infer/tests/frontend/cpp/ConstructorsTest.java +++ b/infer/tests/frontend/cpp/ConstructorsTest.java @@ -70,4 +70,10 @@ public class ConstructorsTest { throws InterruptedException, IOException, InferException { frontendTest("constructor_struct_init_list.cpp"); } + + @Test + public void testStdInitListDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("std_init_list.cpp"); + } }