Partial fix to VAR_EXTERN vs VAR_GLOBAL check. Now considers globals declared in resources too. TODO: recursively check FB declared in the program.
authorMario de Sousa <msousa@fe.up.pt>
Wed, 03 Apr 2013 19:49:52 +0100
changeset 812 6679b6b21214
parent 811 970c582885bf
child 813 0630cc31569f
child 814 a98a4dad904a
Partial fix to VAR_EXTERN vs VAR_GLOBAL check. Now considers globals declared in resources too. TODO: recursively check FB declared in the program.
absyntax_utils/search_var_instance_decl.cc
stage3/declaration_check.cc
stage3/declaration_check.hh
--- a/absyntax_utils/search_var_instance_decl.cc	Fri Feb 22 21:09:59 2013 +0000
+++ b/absyntax_utils/search_var_instance_decl.cc	Wed Apr 03 19:49:52 2013 +0100
@@ -105,6 +105,7 @@
   this->current_vartype = none_vt;
   this->current_option  = none_opt;
   this->search_name = get_var_name_c::get_name(variable);
+  if (NULL == search_scope) return NULL; // NOTE: This is not an ERROR! declaration_check_c, for e.g., relies on this returning NULL!
   return (symbol_c *)search_scope->accept(*this);
 }
 
@@ -112,6 +113,7 @@
   this->current_vartype = none_vt;
   this->current_option  = none_opt;
   this->search_name = get_var_name_c::get_name(variable);
+  if (NULL == search_scope) ERROR;
   search_scope->accept(*this);
   return this->current_vartype;
 }
@@ -120,6 +122,7 @@
   this->current_vartype = none_vt;
   this->current_option  = none_opt;
   this->search_name = get_var_name_c::get_name(variable);
+  if (NULL == search_scope) ERROR;
   search_scope->accept(*this);
   return this->current_option;
 }
--- a/stage3/declaration_check.cc	Fri Feb 22 21:09:59 2013 +0000
+++ b/stage3/declaration_check.cc	Wed Apr 03 19:49:52 2013 +0100
@@ -73,6 +73,7 @@
 declaration_check_c::declaration_check_c(symbol_c *ignore) {
   current_display_error_level = 0;
   current_pou_decl = NULL;
+  current_resource_decl = NULL;
   error_count = 0;
 }
 
@@ -85,36 +86,47 @@
 }
 
 void declaration_check_c::check_global_decl(symbol_c *p_decl) {
-	symbol_c *var_name;
-
-	search_var_instance_decl_c search_var_instance_glo_decl(current_pou_decl);
-	search_var_instance_decl_c search_var_instance_ext_decl(p_decl);
-	function_param_iterator_c fpi(p_decl);
-	while((var_name = fpi.next()) != NULL) {
-      if (fpi.param_direction() == function_param_iterator_c::direction_extref) {
-     	 /* found an external reference parameter. */
-     	symbol_c *glo_decl = search_var_instance_glo_decl.get_decl(var_name);
-        symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name);
-    	if (glo_decl == NULL) {
-    	  STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error an external doesn't mach with any global var.");
-    	  continue;
-    	}
-        if (search_var_instance_glo_decl.get_option(var_name) != search_var_instance_ext_decl.get_option(var_name))
-          STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error an external redefinition option.");
-
-        /* TODO: Check redefinition data type.
-         *       We need a new class (like search_base_type class) to get type id by variable declaration.
-         *  symbol_c *glo_type = ????;
-         *  symbol_c *ext_type = fpi.param_type();
-	 */
-	/* For the moment, we will just use search_base_type_c instead... */
-        symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl);
-        symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl);
-        if (! get_datatype_info_c::is_type_equal(glo_type, ext_type))
-          STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error an external redefinition data type.");
+  if (NULL == current_pou_decl) ERROR;
+  
+  search_var_instance_decl_c search_var_instance_pou_glo_decl(current_pou_decl);
+  search_var_instance_decl_c search_var_instance_res_glo_decl(current_resource_decl);
+  search_var_instance_decl_c search_var_instance_ext_decl(p_decl);
+  function_param_iterator_c  fpi(p_decl);
+  
+  symbol_c *var_name;
+  while((var_name = fpi.next()) != NULL) {
+    if (fpi.param_direction() == function_param_iterator_c::direction_extref) {
+      /* found an external reference parameter. */
+      symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name);
+      
+      // NOTE: Must check the POU first, and RESOURCE second!
+      symbol_c                                       *glo_decl =  search_var_instance_res_glo_decl.get_decl(var_name);           
+      search_var_instance_decl_c *search_var_instance_glo_decl = &search_var_instance_res_glo_decl;
+      if (NULL == glo_decl) {
+        glo_decl                     =  search_var_instance_pou_glo_decl.get_decl(var_name);
+        search_var_instance_glo_decl = &search_var_instance_pou_glo_decl;
       }
-	}
-
+      
+      if (NULL == glo_decl) {
+        STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. The external variable does not match with any global variable.");
+        continue;
+      }
+      
+      if (search_var_instance_glo_decl->get_option(var_name) != search_var_instance_ext_decl.get_option(var_name))
+        STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error.  The external variable options do not match with thos of the global variable.");
+
+      /* TODO: Check redefinition data type.
+       *       We need a new class (like search_base_type class) to get type id by variable declaration.
+       *  symbol_c *glo_type = ????;
+       *  symbol_c *ext_type = fpi.param_type();
+       */
+      /* For the moment, we will just use search_base_type_c instead... */
+      symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl);
+      symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl);
+      if (! get_datatype_info_c::is_type_equal(glo_type, ext_type))
+        STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error.  Data type mismatch between external and global variable declarations.");
+    }
+  }
 }
 
 
@@ -125,7 +137,10 @@
 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
 // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
 void *declaration_check_c::visit(function_block_declaration_c *symbol) {
-  current_pou_decl = symbol;
+  /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside FBs!
+   * current_pou_decl = symbol;  
+   * current_resource_decl = NULL;  
+   */
   /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   if (NULL != symbol->var_declarations)
     symbol->var_declarations->accept(*this);
@@ -138,7 +153,10 @@
 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
 // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
 void *declaration_check_c::visit(program_declaration_c *symbol) {
-  current_pou_decl = symbol;
+  /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside PROGRAMs!
+   * current_pou_decl = symbol;  
+   * current_resource_decl = NULL;  
+   */
   /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   if (NULL != symbol->var_declarations)
     symbol->var_declarations->accept(*this);
@@ -162,9 +180,27 @@
   /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   if (NULL != symbol->resource_declarations)
     symbol->resource_declarations->accept(*this);
-  return NULL;
-}
-
+  current_pou_decl = NULL;
+  return NULL;
+}
+
+/*
+RESOURCE resource_name ON resource_type_name
+   optional_global_var_declarations
+   single_resource_declaration
+END_RESOURCE
+*/
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+// SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, enumvalue_symtable_t enumvalue_symtable;)
+void *declaration_check_c::visit(resource_declaration_c *symbol) {
+  current_resource_decl = symbol;
+  /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
+  symbol->resource_declaration->accept(*this);
+  current_resource_decl = NULL;  
+  return NULL;
+}
+
+/*  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
 void *declaration_check_c::visit(program_configuration_c *symbol) {
   symbol_c *p_decl = program_type_symtable.find_value(symbol->program_type_name);
   if (p_decl == program_type_symtable.end_value())
--- a/stage3/declaration_check.hh	Fri Feb 22 21:09:59 2013 +0000
+++ b/stage3/declaration_check.hh	Wed Apr 03 19:49:52 2013 +0100
@@ -39,6 +39,7 @@
     int error_count;
     int current_display_error_level;
     symbol_c *current_pou_decl;
+    symbol_c *current_resource_decl;
 
 public:
     declaration_check_c(symbol_c *ignore);
@@ -61,5 +62,6 @@
     /* B 1.7 Configuration elements */
     /********************************/
     void *visit(configuration_declaration_c *symbol);
-    void *visit(program_configuration_c *symbol);
+    void *visit(resource_declaration_c      *symbol);
+    void *visit(program_configuration_c     *symbol);
 };