# HG changeset patch # User mjsousa # Date 1375867109 -3600 # Node ID e3800aff352c67ed52bbfe688322b7191029a4f3 # Parent 1e6bf9839ece6093acdfc69b2aa36c37d0779e31 Fix datatype analysis of structured variables that contain arrays in their fields (e.g. var.x1[var2 + 42].y1). diff -r 1e6bf9839ece -r e3800aff352c stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Mon Aug 05 15:57:00 2013 +0100 +++ b/stage3/fill_candidate_datatypes.cc Wed Aug 07 10:18:29 2013 +0100 @@ -1112,12 +1112,29 @@ /* if we were to want the data type of the array itself, then we should call_param_name * search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable) */ - symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol); - if (NULL != result) add_datatype_to_candidate_list(symbol, result); + add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol)); /* will only add if non NULL */ /* recursively call the subscript list, so we can check the data types of the expressions used for the subscripts */ symbol->subscript_list->accept(*this); + /* recursively call the subscripted_variable. We need to do this since the array variable may be stored inside a structured + * variable (i.e. if it is an element inside a struct), in which case we want to recursively visit every element of the struct, + * as it may contain more arrays whose subscripts must also be visited! + * e.g. structvar.a1[v1+2].b1.c1[v2+3].d1 + * TYPE + * d_s: STRUCT d1: int; d2: int; + * d_a: ARRAY [1..3] OF d_s; + * c_s: STRUCT c1: d_a; c2: d_a; + * b_s: STRUCT b1: c_s; b2: c_s; + * b_a: ARRAY [1..3] OF b_s; + * a_s: STRUCT a1: b_a; a2: b_a; + * END_TYPE + * VAR + * structvar: a_s; + * END_VAR + */ + symbol->subscripted_variable->accept(*this); + if (debug) std::cout << "ARRAY_VAR [" << symbol->candidate_datatypes.size() << "]\n"; return NULL; } @@ -1136,11 +1153,18 @@ * this into account! */ // SYM_REF2(structured_variable_c, record_variable, field_selector) -/* NOTE: We do not need to recursively determine the data types of each field_selector, as the search_varfb_instance_type - * will do that for us. So we determine the candidate datatypes only for the full structured_variable. - */ void *fill_candidate_datatypes_c::visit(structured_variable_c *symbol) { + /* NOTE: We do not need to recursively determine the data types of each field_selector, as the search_varfb_instance_type + * will do that for us. So we determine the candidate datatypes only for the full structured_variable. + */ add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol)); /* will only add if non NULL */ + /* However, we do need to visit each record type recursively! + * Remember that a structured variable may be stored inside an array (e.g. arrayvar[33].elem1) + * The array subscripts may contain a complex expression (e.g. arrayvar[ varx + 33].elem1) whose datatype must be correctly determined! + * The expression, may even contain a function call to an overloaded function! + * (e.g. arrayvar[ varx + TRUNC(realvar)].elem1) + */ + symbol->record_variable->accept(*this); return NULL; } diff -r 1e6bf9839ece -r e3800aff352c stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Mon Aug 05 15:57:00 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Wed Aug 07 10:18:29 2013 +0100 @@ -662,6 +662,14 @@ void *narrow_candidate_datatypes_c::visit(array_variable_c *symbol) { /* we need to check the data types of the expressions used for the subscripts... */ symbol->subscript_list->accept(*this); + + /* Set the datatype of the subscripted variable and visit it recursively. For the reason why we do this, */ + /* Please read the comments in the array_variable_c and structured_variable_c visitors in the fill_candidate_datatypes.cc file! */ + symbol->subscripted_variable->accept(*this); // visit recursively + + if (symbol->subscripted_variable->candidate_datatypes.size() == 1) + symbol->subscripted_variable->datatype = symbol->subscripted_variable->candidate_datatypes[0]; // set the datatype + return NULL; } @@ -681,6 +689,24 @@ +/* record_variable '.' field_selector */ +/* WARNING: input and/or output variables of function blocks + * may be accessed as fields of a structured variable! + * Code handling a structured_variable_c must take + * this into account! + */ +// SYM_REF2(structured_variable_c, record_variable, field_selector) +void *narrow_candidate_datatypes_c::visit(structured_variable_c *symbol) { + /* Set the datatype of the record_variable and visit it recursively. For the reason why we do this, */ + /* Please read the comments in the array_variable_c and structured_variable_c visitors in the fill_candidate_datatypes.cc file! */ + symbol->record_variable->accept(*this); // visit recursively + + if (symbol->record_variable->candidate_datatypes.size() == 1) + symbol->record_variable->datatype = symbol->record_variable->candidate_datatypes[0]; // set the datatype + + return NULL; +} + /******************************************/ /* B 1.4.3 - Declaration & Initialisation */ diff -r 1e6bf9839ece -r e3800aff352c stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Mon Aug 05 15:57:00 2013 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Wed Aug 07 10:18:29 2013 +0100 @@ -189,6 +189,7 @@ /*************************************/ void *visit(array_variable_c *symbol); void *visit(subscript_list_c *symbol); + void *visit(structured_variable_c *symbol); /******************************************/ /* B 1.4.3 - Declaration & Initialisation */ diff -r 1e6bf9839ece -r e3800aff352c stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Mon Aug 05 15:57:00 2013 +0100 +++ b/stage3/print_datatypes_error.cc Wed Aug 07 10:18:29 2013 +0100 @@ -134,6 +134,10 @@ bool function_invocation_error = false; const char *POU_str = NULL; +debug_c::print("print_datatypes_error_c::handle_function_invocation() CALLED!\n"); +debug_c::print(fcall); + + if (generic_function_call_t::POU_FB == fcall_data.POU_type) POU_str = "FB"; if (generic_function_call_t::POU_function == fcall_data.POU_type) POU_str = "function"; if (NULL == POU_str) ERROR; @@ -204,7 +208,11 @@ } } if (NULL != fcall_data.nonformal_operand_list) { +debug_c::print("print_datatypes_error_c::handle_function_invocation() CALLING ---> fcall_data.nonformal_operand_list->accept(*this)!\n"); +debug_c::print_ast(fcall_data.nonformal_operand_list); +debug_c::print("print_datatypes_error_c::handle_function_invocation() LIST_END\n"); fcall_data.nonformal_operand_list->accept(*this); +debug_c::print("print_datatypes_error_c::handle_function_invocation() RETURNED <--- fcall_data.nonformal_operand_list->accept(*this)!\n"); if (f_decl) for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) { /* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */ @@ -569,6 +577,10 @@ /* subscripted_variable '[' subscript_list ']' */ // SYM_REF2(array_variable_c, subscripted_variable, subscript_list) void *print_datatypes_error_c::visit(array_variable_c *symbol) { + /* the subscripted variable may be a structure or another array variable, that must also be visisted! */ + /* Please read the comments in the array_variable_c and structured_variable_c visitors in the fill_candidate_datatypes.cc file! */ + symbol->subscripted_variable->accept(*this); + if (symbol->candidate_datatypes.size() == 0) STAGE3_ERROR(0, symbol, symbol, "Array variable not declared in this scope."); @@ -598,13 +610,13 @@ * this into account! */ // SYM_REF2(structured_variable_c, record_variable, field_selector) -/* NOTE: We do not recursively determine the data types of each field_selector in fill_candidate_datatypes_c, - * so it does not make sense to recursively visit all the field_selectors to print out error messages. - * Maybe in the future, if we find the need to print out more detailed error messages, we might do it that way. For now, we don't! - */ void *print_datatypes_error_c::visit(structured_variable_c *symbol) { + /* the record variable may be another structure or even an array variable, that must also be visisted! */ + /* Please read the comments in the array_variable_c and structured_variable_c visitors in the fill_candidate_datatypes.cc file! */ + symbol->record_variable->accept(*this); + if (symbol->candidate_datatypes.size() == 0) - STAGE3_ERROR(0, symbol, symbol, "Undeclared structured/FB variable."); + STAGE3_ERROR(0, symbol, symbol, "Undeclared structured (or FB) variable, or non-existant field (variable) in structure (FB)."); return NULL; }