# HG changeset patch # User Mario de Sousa # Date 1333031978 -3600 # Node ID 6ae697b34f2d290bfa7fed17b8684d283dcaa181 # Parent 6f4083fe169e9555a96cb866a1d5ae1a51c332e6 Print correct error message when handling IL function calls. diff -r 6f4083fe169e -r 6ae697b34f2d stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Thu Mar 15 13:23:09 2012 +0000 +++ b/stage3/print_datatypes_error.cc Thu Mar 29 15:39:38 2012 +0100 @@ -216,7 +216,50 @@ for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) { /* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */ - if (NULL == param_value->datatype) { + /* This handle_function_invocation() will be called to handle IL function calls, where the first parameter comes from the previous IL instruction. + * In this case, the previous IL instruction will be artifically (and temporarily) added to the begining ot the parameter list + * so we (in this function) can handle this situation like all the other function calls. + * However, + * a) if NO previous IL function exists, then we get a fake previous IL function, with no location data (i.e. not found anywhere in the source code. + * b) the function call may actually have several prev IL instructions (if several JMP instructions jump directly to the il function call). + * In order to handle these situations gracefully, we first check whether the first parameter is really an IL istruction! + */ + il_instruction_c *il_instruction_symbol = dynamic_cast(param_value); + if ((NULL != il_instruction_symbol) && (i == 1)) { + /* We are in a situation where an IL function call is passed the first parameter, which is actually the previous IL instruction */ + /* However, this is really a fake previous il instruction (see visit(il_instruction_c *) ) + * We will iterate through all the real previous IL instructions, and analyse each of them one by one */ + if (il_instruction_symbol->prev_il_instruction.size() == 0) { + function_invocation_error = true; + STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((identifier_c *)fcall_data.function_name)->value); + } +#if 0 + /* NOTE: We currently comment out this code... + * This does not currently work, since the narrow operation is currently done on the intersection + * of all the previous IL instructions, so we currently either accept them all, or none at all. + * In order to be able to produce these user freindly error messages, we will need to update the + * narrow algorithm. We leave this untill somebody aks for it... + * So, for now, we simply comment out this code. + */ + for (unsigned int p = 0; p < il_instruction_symbol->prev_il_instruction.size(); p++) { + symbol_c *value = il_instruction_symbol->prev_il_instruction[p]; + if (!is_type_valid(value->datatype)) { + function_invocation_error = true; + STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((identifier_c *)fcall_data.function_name)->value); + STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value); + } + } +#else + if (!is_type_valid(il_instruction_symbol->datatype)) { + function_invocation_error = true; + STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value); + } +#endif + if (function_invocation_error) + /* when handling a IL function call, and an error is found in the first parameter, then we bug out and do not print out any more error messages. */ + return; + } + else if (!is_type_valid(param_value->datatype)) { function_invocation_error = true; STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value); } @@ -630,6 +673,10 @@ void *print_datatypes_error_c::visit(il_instruction_c *symbol) { if (NULL != symbol->il_instruction) { il_instruction_c tmp_prev_il_instruction(NULL, NULL); +#if 0 + /* NOTE: The following is currently no longer needed. Since the following code is actually cool, + * we don't delete it, but simply comment it out. It might just come in handy later on... + */ /* When handling a il function call, this fake_prev_il_instruction may be used as a standard function call parameter, so it is important that * it contain some valid location info so error messages make sense. */ @@ -650,7 +697,8 @@ * be reset to the correct value when we call intersect_prev_candidate_datatype_lists() later on... */ } - /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the +#endif + /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the * list of the prev_il_instructions. * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), * and shove that data into this single variable.