# HG changeset patch # User mjsousa # Date 1421410814 0 # Node ID 4c235d65afdd1793631db0f363bdcb2ef2c3c380 # Parent d4f8931d80cd0724d6e84203cc5fe02ca304b076 Do not allow constant_propagation algorithm go into infinite loop when analysing code with circular references. diff -r d4f8931d80cd -r 4c235d65afdd stage3/constant_folding.cc --- a/stage3/constant_folding.cc Fri Jan 16 11:17:33 2015 +0000 +++ b/stage3/constant_folding.cc Fri Jan 16 12:20:14 2015 +0000 @@ -1416,6 +1416,8 @@ return NULL; } + +#include // std::find void *constant_propagation_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl, bool is_global_var) { type_decl->accept(*this); // Do constant folding of the initial value, and literals in subranges! (we will probably be doing this multiple times for the same init value, but this is safe as the cvalue is idem-potent) symbol_c *init_value = type_initial_value_c::get(type_decl); @@ -1441,8 +1443,17 @@ // Remmeber that in this case we will recursively visit the FB type declaration!! function_block_declaration_c *fb_type = itr->second; if (NULL == fb_type) ERROR; // syntax parsing should not allow this! - // TODO: detect whether we are already currently visiting this exact same FB declaration (possible with -p option), so we do not get into an infinite loop!! - fb_type->accept(*this); + // WARNING: Before calling fb_type->accept(*this), we must first determine whether we are already currently visiting this exact + // same FB declaration (possible with -p option), so we do not get into an infinite loop!! + // NOTE: We use the std::find() standard algorithm, since the std::stack and std::deque do not have the find() member function. + // We could alternatively use a std::set instead of std::deque, but then it would not be evident that insertion and deletion + // of fb_types follows a push() and pop() algorithm typical of stacks. + if (std::find(fbs_currently_being_visited.begin(), fbs_currently_being_visited.end(), fb_type) == fbs_currently_being_visited.end()) { + // The fb_type is not in the fbs_currently_being_visited stack, so we push it onto the stack, and then visit it!! + fbs_currently_being_visited.push_back(fb_type); + fb_type->accept(*this); + fbs_currently_being_visited.pop_back(); + } return NULL; } diff -r d4f8931d80cd -r 4c235d65afdd stage3/constant_folding.hh --- a/stage3/constant_folding.hh Fri Jan 16 11:17:33 2015 +0000 +++ b/stage3/constant_folding.hh Fri Jan 16 12:20:14 2015 +0000 @@ -201,6 +201,7 @@ +#include class constant_propagation_c : public constant_folding_c { public: @@ -212,6 +213,9 @@ symbol_c *current_configuration; map_values_t *values; map_values_t var_global_values; + /* A stack of all the FB declarations currently being recursively constant propagated */ + std::deque fbs_currently_being_visited; // We use a deque instead of stack, so we can search in the stack using direct access to its elements! + void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl, bool is_global_var = false); void *handle_var_decl (symbol_c *var_list, bool fixed_init_value); // Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!