Partial fix to VAR_EXTERN vs VAR_GLOBAL check. Now considers globals declared in resources too. TODO: recursively check FB declared in the program.
--- 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);
};