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;
}