# HG changeset patch # User mjsousa # Date 1420743843 0 # Node ID 2064a22cc1f2df666495981cb0d205a057fb5ffa # Parent 837c6532a9b83e3e09c29aee3fc53643c7a7bc28 Correctly analyse external<->global var compatibility when using variable sized arrays (TODO: does not yet work for FBs!) diff -r 837c6532a9b8 -r 2064a22cc1f2 absyntax_utils/get_datatype_info.cc --- a/absyntax_utils/get_datatype_info.cc Tue Dec 30 23:32:04 2014 +0000 +++ b/absyntax_utils/get_datatype_info.cc Thu Jan 08 19:04:03 2015 +0000 @@ -677,17 +677,23 @@ subrange_c *subrange_1 = dynamic_cast(subrange_list_1->elements[i]); subrange_c *subrange_2 = dynamic_cast(subrange_list_2->elements[i]); if ((NULL == subrange_1) || (NULL == subrange_2)) ERROR; - #if 0 - /* An alternative method of checking whether the subranges have the same values, using the result of the constant folding agorithm. + + /* check whether the subranges have the same values, using the result of the constant folding agorithm. * This method has the drawback that it inserts a dependency on having to run the constant folding algorithm before * the get_datatype_info_c::is_type_equal() method is called. - * The probably slower alternative of comparing the strings themselves is therefor used. + * This is why we implement an alternative method in case the subrange limits have not yet been reduced to a cvalue! */ - if (!constant_folding_c::is_equal_cvalue(subrange_1->lower_limit, subrange_2->lower_limit)) return false; - if (!constant_folding_c::is_equal_cvalue(subrange_1->upper_limit, subrange_2->upper_limit)) return false; - #endif - if (normalize_integer(subrange_1->lower_limit) != normalize_integer(subrange_2->lower_limit)) return false; - if (normalize_integer(subrange_1->upper_limit) != normalize_integer(subrange_2->upper_limit)) return false; + if ( (subrange_1->lower_limit->const_value._int64.is_valid() || subrange_1->lower_limit->const_value._uint64.is_valid()) + && (subrange_2->lower_limit->const_value._int64.is_valid() || subrange_2->lower_limit->const_value._uint64.is_valid()) + && (subrange_1->upper_limit->const_value._int64.is_valid() || subrange_1->upper_limit->const_value._uint64.is_valid()) + && (subrange_2->upper_limit->const_value._int64.is_valid() || subrange_2->upper_limit->const_value._uint64.is_valid()) + ) { + if (! (subrange_1->lower_limit->const_value == subrange_2->lower_limit->const_value)) return false; + if (! (subrange_1->upper_limit->const_value == subrange_2->upper_limit->const_value)) return false; + } else { + if (normalize_integer(subrange_1->lower_limit) != normalize_integer(subrange_2->lower_limit)) return false; + if (normalize_integer(subrange_1->upper_limit) != normalize_integer(subrange_2->upper_limit)) return false; + } } return is_type_equal(search_base_type_c::get_basetype_decl(array_1->non_generic_type_name), diff -r 837c6532a9b8 -r 2064a22cc1f2 stage3/stage3.cc --- a/stage3/stage3.cc Tue Dec 30 23:32:04 2014 +0000 +++ b/stage3/stage3.cc Thu Jan 08 19:04:03 2015 +0000 @@ -55,6 +55,16 @@ } +/* In order to correctly handle variable sized arrays + * declaration_safety() must only be run after constant folding! + * NOTE that the dependency does not resides directly in declaration_check_c, + * but rather indirectly in the call to get_datatype_info_c::is_type_equal() + * which may in turn call get_datatype_info_c::is_arraytype_equal_relaxed() + * + * Example of a variable sized array: + * VAR_EXTERN CONSTANT max: INT; END_VAR; + * VAR_EXTERN xx: ARRAY [1..max] OF INT; END_VAR; + */ static int declaration_safety(symbol_c *tree_root){ declaration_check_c declaration_check(tree_root); tree_root->accept(declaration_check); @@ -138,9 +148,9 @@ int stage3(symbol_c *tree_root, symbol_c **ordered_tree_root) { int error_count = 0; error_count += enum_declaration_check(tree_root); - error_count += declaration_safety(tree_root); error_count += flow_control_analysis(tree_root); error_count += constant_propagation(tree_root); + error_count += declaration_safety(tree_root); error_count += type_safety(tree_root); error_count += lvalue_check(tree_root); error_count += array_range_check(tree_root);