diff -r a7d9e0b8636b -r 9c6c588fd708 stage3/lvalue_check.cc --- a/stage3/lvalue_check.cc Wed Feb 19 22:25:10 2014 +0100 +++ b/stage3/lvalue_check.cc Wed Feb 19 22:27:11 2014 +0100 @@ -114,7 +114,7 @@ * when an expression is found, we may replace this check with an assertion... * if (NULL == struct_elem) ERROR; */ - symbol_c *struct_elem = decompose_lvalue.next_part(); + symbol_c *struct_elem = decompose_lvalue.get_next(); if (NULL == struct_elem) return; symbol_c *type_decl = search_var_instance_decl->get_decl(struct_elem); @@ -135,7 +135,7 @@ function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(basetype_id); if (function_block_type_symtable.end_value() == fb_decl) return; - while (NULL != (struct_elem = decompose_lvalue.next_part())) { + while (NULL != (struct_elem = decompose_lvalue.get_next())) { search_var_instance_decl_c fb_search_var_instance_decl(fb_decl); if (search_var_instance_decl_c::output_vt == fb_search_var_instance_decl.get_vartype(struct_elem)) { STAGE3_ERROR(0, struct_elem, struct_elem, "Assignment to FB output variable is not allowed."); @@ -156,16 +156,13 @@ void lvalue_check_c::check_assignment_to_constant(symbol_c *lvalue) { unsigned int option = search_var_instance_decl->get_option(lvalue); if (option == search_var_instance_decl_c::constant_opt) { - STAGE3_ERROR(0, lvalue, lvalue, "Assignment to CONSTANT variables is not be allowed."); + STAGE3_ERROR(0, lvalue, lvalue, "Assignment to CONSTANT variables is not allowed."); } } /* No assigning values to expressions. */ void lvalue_check_c::check_assignment_to_expression(symbol_c *lvalue) { - /* This may occur in function invocations, when passing values (possibly an expression) to one - * of the function's OUTPUT or IN_OUT parameters. - */ /* This may occur in function invocations, when passing values (possibly an expression) to one * of the function's OUTPUT or IN_OUT parameters. */ @@ -233,21 +230,39 @@ (typeid( *lvalue ) == typeid( neg_expression_c )) || (typeid( *lvalue ) == typeid( not_expression_c )) || (typeid( *lvalue ) == typeid( function_invocation_c ))) - STAGE3_ERROR(0, lvalue, lvalue, "Assigning an expression to an OUT or IN_OUT parameter is not allowed."); + STAGE3_ERROR(0, lvalue, lvalue, "Assignment to an expression or a literal value is not allowed."); } +/* No assigning values to IL lists. */ +void lvalue_check_c::check_assignment_to_il_list(symbol_c *lvalue) { + /* This may occur in formal invocations in IL, where an embedded IL list may be used instead of a symbolic_variable + * when passing an IN_OUT parameter! Note that it will never occur to OUT parameters, as the syntax does not allow it, + * although this does not affect out algorithm here! + */ + if ( + /****************************************/ + /* B.2 - Language IL (Instruction List) */ + /****************************************/ + /***********************************/ + /* B 2.1 Instructions and Operands */ + /***********************************/ + (typeid( *lvalue ) == typeid( simple_instr_list_c))) + STAGE3_ERROR(0, lvalue, lvalue, "Assigning an IL list to an IN_OUT parameter is not allowed."); +} void lvalue_check_c::verify_is_lvalue(symbol_c *lvalue) { + if (NULL == lvalue) return; // missing operand in source code being compiled. Error will be caught and reported by datatype checking! int init_error_count = error_count; /* stop the checks once an error has been found... */ if (error_count == init_error_count) check_assignment_to_expression(lvalue); + if (error_count == init_error_count) check_assignment_to_il_list (lvalue); if (error_count == init_error_count) check_assignment_to_controlvar(lvalue); - if (error_count == init_error_count) check_assignment_to_output(lvalue); - if (error_count == init_error_count) check_assignment_to_constant(lvalue); + if (error_count == init_error_count) check_assignment_to_output (lvalue); + if (error_count == init_error_count) check_assignment_to_constant (lvalue); } @@ -261,6 +276,12 @@ */ #include /* required for strcmp() */ void lvalue_check_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl) { + /* if data type semantic verification was unable to determine which function is being called, + * then it does not make sense to go ahead and check for lvalues to unknown parameters. + * We simply bug out! + */ + if (NULL == f_decl) return; + symbol_c *call_param_value; identifier_c *param_name; function_param_iterator_c fp_iterator(f_decl); @@ -286,9 +307,9 @@ /* If the parameter is either OUT or IN_OUT, we check if 'call_param_value' is a valid lvalue */ if ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction)) verify_is_lvalue(call_param_value); - /* parameter values to IN parameters may be expressions with function invocations that must also be checked! */ - if (function_param_iterator_c::direction_in == param_direction) - call_param_value->accept(*this); + /* parameter values to IN parameters may be expressions with function invocations that must also be checked! */ + /* parameter values to OUT or IN_OUT parameters may contain arrays, whose subscripts contain expressions that must be checked! */ + call_param_value->accept(*this); } } } @@ -326,10 +347,9 @@ /* If the parameter is either OUT or IN_OUT, we check if 'call_param_value' is a valid lvalue */ if ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction)) verify_is_lvalue(call_param_value); - /* parameter values to IN parameters may be expressions with function invocations that must also be checked! */ - if (function_param_iterator_c::direction_in == param_direction) - call_param_value->accept(*this); - + /* parameter values to IN parameters may be expressions with function invocations that must also be checked! */ + /* parameter values to OUT or IN_OUT parameters may contain arrays, whose subscripts contain expressions that must be checked! */ + call_param_value->accept(*this); } } }