-
Notifications
You must be signed in to change notification settings - Fork 274
[TG-7815] Fix bug in get_recursively_instantiated_type #4913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
4abbd7a
cf6d6fb
e4b7363
8125a9f
ec69b1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -126,86 +126,24 @@ pointer_typet select_pointer_typet::specialize_generics( | |
/// such instantiation exists. | ||
optionalt<pointer_typet> | ||
select_pointer_typet::get_recursively_instantiated_type( | ||
const irep_idt ¶meter_name, | ||
const generic_parameter_specialization_mapt | ||
&generic_parameter_specialization_map) const | ||
irep_idt parameter_name, | ||
generic_parameter_specialization_mapt | ||
generic_parameter_specialization_map) const | ||
{ | ||
generic_parameter_recursion_trackingt visited; | ||
const size_t max_depth = | ||
generic_parameter_specialization_map.find(parameter_name)->second.size(); | ||
|
||
irep_idt current_parameter = parameter_name; | ||
for(size_t depth = 0; depth < max_depth; depth++) | ||
while(true) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good, but since taking a map by value like this is quite unusual please add comments noting the strategy you're using here and why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The map itself is not taken by value. I don't think we need to document why passing a struct by value is OK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what you mean by "not taken by value". We do make a copy here, so we can pop from the stacks of particular parameters in the map just for the sake of finding the parameter specialization, but at the call site of this function we need to keep the original full information. I agree that adding a note that points this out is useful (not arguing why it's ok, just to make the reader notice), I missed it myself at first. |
||
{ | ||
const auto retval = get_recursively_instantiated_type( | ||
current_parameter, generic_parameter_specialization_map, visited, depth); | ||
if(retval.has_value()) | ||
{ | ||
CHECK_RETURN(!is_java_generic_parameter(*retval)); | ||
return retval; | ||
} | ||
CHECK_RETURN(visited.empty()); | ||
|
||
const auto &entry = | ||
generic_parameter_specialization_map.find(current_parameter) | ||
->second.back(); | ||
current_parameter = to_java_generic_parameter(entry).get_name(); | ||
} | ||
return {}; | ||
} | ||
|
||
/// See get_recursively instantiated_type, the additional parameters just track | ||
/// the recursion to prevent visiting the same depth again and specify which | ||
/// stack depth is analyzed. | ||
/// \param parameter_name: The name of the generic parameter type we want to | ||
/// have instantiated | ||
/// \param generic_parameter_specialization_map: Map of type names to | ||
/// specialization stack | ||
/// \param visited: Tracks the visited parameter names | ||
/// \param depth: Stack depth to analyze | ||
/// \return if this type is not a generic type, it is returned as a valid | ||
/// instantiation, if nothing can be found at the given depth, en empty | ||
/// optional is returned | ||
optionalt<pointer_typet> | ||
select_pointer_typet::get_recursively_instantiated_type( | ||
const irep_idt ¶meter_name, | ||
const generic_parameter_specialization_mapt | ||
&generic_parameter_specialization_map, | ||
generic_parameter_recursion_trackingt &visited, | ||
const size_t depth) const | ||
{ | ||
const auto &val = generic_parameter_specialization_map.find(parameter_name); | ||
INVARIANT( | ||
val != generic_parameter_specialization_map.end(), | ||
"generic parameter must be a key in map"); | ||
|
||
const auto &replacements = val->second; | ||
|
||
INVARIANT( | ||
depth < replacements.size(), "cannot access elements outside stack"); | ||
|
||
// Check if there is a recursion loop, if yes return with nothing found | ||
if(visited.find(parameter_name) != visited.end()) | ||
{ | ||
return {}; | ||
} | ||
|
||
const size_t index = (replacements.size() - 1) - depth; | ||
const auto &type = replacements[index]; | ||
|
||
if(!is_java_generic_parameter(type)) | ||
{ | ||
return type; | ||
auto types_it = generic_parameter_specialization_map.find(parameter_name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commit message: note what the bug was and how this fixes it |
||
INVARIANT( | ||
types_it != generic_parameter_specialization_map.end(), | ||
"Type parameter must have a type argument"); | ||
if(types_it->second.empty()) | ||
return {}; | ||
reference_typet type = types_it->second.back(); | ||
types_it->second.pop_back(); | ||
if(!is_java_generic_parameter(type)) | ||
return std::move(type); | ||
parameter_name = to_java_generic_parameter(type).get_name(); | ||
} | ||
|
||
visited.insert(parameter_name); | ||
const auto inst_val = get_recursively_instantiated_type( | ||
to_java_generic_parameter(type).get_name(), | ||
generic_parameter_specialization_map, | ||
visited, | ||
depth); | ||
visited.erase(parameter_name); | ||
return inst_val; | ||
} | ||
|
||
std::set<struct_tag_typet> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be updated slightly - it sounds l like it's only handling the recursion case (because it's just moved from the function that was breaking recursion). Also, move the documentation to the header.