Correctly analyse external<->global var compatibility when using variable sized arrays (TODO: does not yet work for FBs!)
--- 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_c *>(subrange_list_1->elements[i]);
subrange_c *subrange_2 = dynamic_cast<subrange_c *>(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),
--- 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);