in source/FrameSet.cpp [396:456]
Frame FrameSet::propagate_frames(
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,
std::vector<std::reference_wrapper<const Frame>> frames,
std::vector<const Feature*>& via_type_of_features_added) const {
int distance = std::numeric_limits<int>::max();
auto origins = MethodSet::bottom();
auto field_origins = FieldSet::bottom();
auto inferred_features = FeatureMayAlwaysSet::bottom();
for (const Frame& frame : frames) {
if (frame.distance() >= maximum_source_sink_distance) {
continue;
}
distance = std::min(distance, frame.distance() + 1);
origins.join_with(frame.origins());
field_origins.join_with(frame.field_origins());
// Note: This merges user features with existing inferred features.
inferred_features.join_with(frame.features());
materialize_via_type_of_ports(
callee,
context,
frame,
source_register_types,
via_type_of_features_added,
inferred_features);
materialize_via_value_of_ports(
callee, context, frame, source_constant_arguments, inferred_features);
}
if (distance == std::numeric_limits<int>::max()) {
return Frame::bottom();
}
return Frame(
kind_,
callee_port,
callee,
/* field_callee */ nullptr, // Since propagate is only called at method
// callsites and not field accesses
call_position,
distance,
std::move(origins),
std::move(field_origins),
std::move(inferred_features),
/* locally_inferred_features */ FeatureMayAlwaysSet::bottom(),
/* user_features */ FeatureSet::bottom(),
/* via_type_of_ports */ {},
/* via_value_of_ports */ {},
/* local_positions */ {},
/* canonical_names */ {});
}