Correctly analyse external<->global var compatibility when using variable sized arrays (TODO: does not yet work for FBs!)
authormjsousa
Thu, 08 Jan 2015 19:04:03 +0000
changeset 986 2064a22cc1f2
parent 985 837c6532a9b8
child 987 562b67922966
child 991 7c01878bd525
Correctly analyse external<->global var compatibility when using variable sized arrays (TODO: does not yet work for FBs!)
absyntax_utils/get_datatype_info.cc
stage3/stage3.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_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);