@@ -156,7 +156,7 @@ struct
156156 | n :: stack ->
157157 let cfgnode = Arg.Node. cfgnode n in
158158 match cfgnode with
159- | Function _ -> (* TODO: can this be done without cfgnode? *)
159+ | Function cfgnode_fd -> (* TODO: can this be done without cfgnode? *)
160160 begin match stack with
161161 (* | [] -> failwith "StackArg.next: return stack empty" * )
162162 | [] -> [] (* main return *)
@@ -171,7 +171,7 @@ struct
171171 | _ -> None
172172 )
173173 in
174- let entry_lval_args =
174+ let (entry_lval, entry_args) =
175175 Arg. next call_n
176176 (* filter because infinite loops starting with function call
177177 will have another Neg(1) edge from the head *)
@@ -180,12 +180,18 @@ struct
180180 | InlineEntry (lval , _ , args ) -> Some (lval, args)
181181 | _ -> None
182182 )
183+ |> List. sort_uniq [% ord: CilType.Lval. t option * CilType.Exp. t list ] (* TODO: deduplicate unique element in O(n) *)
184+ |> (function
185+ | [lval_args] -> lval_args
186+ | _ -> assert false (* all calls from a node must have same args and lval, even if called function might be different via function pointer *)
187+ )
183188 in
184189 Arg. next n
185190 |> List. filter_map (fun (edge , to_n ) ->
186191 match edge with
187- | InlineReturn (lval , _ , args ) -> (* TODO: should also check fundec component equality? might be different for ambiguous calls via function pointer *)
188- if BatList. mem_cmp Arg.Node. compare to_n call_next && BatList. mem_cmp [% ord: CilType.Lval. t option * CilType.Exp. t list ] (lval, args) entry_lval_args then (
192+ | InlineReturn (lval , fd , args ) ->
193+ assert (CilType.Fundec. equal fd cfgnode_fd); (* fd in return node should be the same as in InlineReturn edge *)
194+ if BatList. mem_cmp Arg.Node. compare to_n call_next && [% eq: CilType.Lval. t option ] lval entry_lval && [% eq: CilType.Exp. t list ] args entry_args then (
189195 let to_n' = to_n :: call_stack in
190196 Some (edge, to_n')
191197 )
0 commit comments