CallPositionFrames CallPositionFrames::propagate()

in source/CallPositionFrames.cpp [233:288]


CallPositionFrames CallPositionFrames::propagate(
    const Method* callee,
    const AccessPath& callee_port,
    const Position* call_position,
    int maximum_source_sink_distance,
    Context& context,
    const std::vector<const DexType * MT_NULLABLE>& source_register_types,
    const std::vector<std::optional<std::string>>& source_constant_arguments)
    const {
  if (is_bottom()) {
    return CallPositionFrames::bottom();
  }

  CallPositionFrames result;
  auto partitioned_by_kind = partition_map<const Kind*>(
      [](const Frame& frame) { return frame.kind(); });

  for (const auto& [kind, frames] : partitioned_by_kind) {
    std::vector<std::reference_wrapper<const Frame>> non_crtex_frames;
    std::vector<std::reference_wrapper<const Frame>> crtex_frames;
    for (const auto& frame : frames) {
      if (frame.get().is_crtex_producer_declaration()) {
        crtex_frames.push_back(frame);
      } else {
        non_crtex_frames.push_back(frame);
      }
    }

    result.join_with(propagate_crtex_frames(
        callee,
        callee_port,
        call_position,
        maximum_source_sink_distance,
        context,
        source_register_types,
        crtex_frames));

    // Non-CRTEX frames can be joined into the same callee
    std::vector<const Feature*> via_type_of_features_added;
    auto non_crtex_frame = propagate_frames(
        callee,
        callee_port,
        call_position,
        maximum_source_sink_distance,
        context,
        source_register_types,
        source_constant_arguments,
        non_crtex_frames,
        via_type_of_features_added);
    if (!non_crtex_frame.is_bottom()) {
      result.add(non_crtex_frame);
    }
  }

  return result;
}