# HG changeset patch # User Mario de Sousa # Date 1334516193 -3600 # Node ID 35d391c38a30bffa89b39adbb07ffd3c3ddbc9d6 # Parent dc6906338042bf139215bcacdca6c558c1ac2248 Fixing some bugs in lvalue checking (other bugs remain - to be fixed later) diff -r dc6906338042 -r 35d391c38a30 stage3/Makefile.in --- a/stage3/Makefile.in Sat Apr 14 20:02:36 2012 +0200 +++ b/stage3/Makefile.in Sun Apr 15 19:56:33 2012 +0100 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -74,7 +74,8 @@ flow_control_analysis.$(OBJEXT) \ fill_candidate_datatypes.$(OBJEXT) \ narrow_candidate_datatypes.$(OBJEXT) \ - print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT) + print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT) \ + lvalue_check.$(OBJEXT) libstage3_a_OBJECTS = $(am_libstage3_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config depcomp = $(SHELL) $(top_srcdir)/config/depcomp @@ -195,7 +196,8 @@ fill_candidate_datatypes.cc \ narrow_candidate_datatypes.cc \ print_datatypes_error.cc \ - datatype_functions.cc + datatype_functions.cc \ + lvalue_check.cc all: all-am @@ -277,6 +279,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flow_control_analysis.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lvalue_check.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/narrow_candidate_datatypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_datatypes_error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stage3.Po@am__quote@ diff -r dc6906338042 -r 35d391c38a30 stage3/lvalue_check.cc --- a/stage3/lvalue_check.cc Sat Apr 14 20:02:36 2012 +0200 +++ b/stage3/lvalue_check.cc Sun Apr 15 19:56:33 2012 +0100 @@ -70,20 +70,23 @@ return error_found; } + +#include /* No writing to iterator variables (used in FOR loops) inside the loop itself */ -void lvalue_check_c::check_for_controlvar_assignment(symbolic_variable_c * lvalue) { +void lvalue_check_c::check_assignment_to_controlvar(symbol_c *lvalue) { for (unsigned int i = 0; i < control_variables.size(); i++) { symbolic_variable_c *cvar = (symbolic_variable_c *)control_variables[i]; - if (strcasecmp(((identifier_c *)lvalue->var_name)->value, ((identifier_c *)cvar->var_name)->value) == 0) { + if (strcasecmp(((identifier_c *)((symbolic_variable_c *)lvalue)->var_name)->value, ((identifier_c *)((symbolic_variable_c *)cvar)->var_name)->value) == 0) { STAGE3_ERROR(0, lvalue, lvalue, "Assignment to FOR control variable are not be allowed."); break; } } } + /* fb_instance.var := ... is not valid if var is output (not input ??) variable */ -void lvalue_check_c::check_output_assignment(symbolic_variable_c * lvalue) { - symbol_c *type_id = search_varfb_instance_type->get_basetype_id(lvalue->var_name); +void lvalue_check_c::check_assignment_to_output(symbol_c * lvalue) { + symbol_c *type_id = search_varfb_instance_type->get_basetype_id(lvalue); if (NULL != type_id) { function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(type_id); if (function_block_type_symtable.end_value() != fb_decl) { @@ -91,49 +94,83 @@ structured_variable_c * str_var = (structured_variable_c *)lvalue; unsigned int vartype = search_var_instance_decl.get_vartype(str_var->field_selector); if (vartype == search_var_instance_decl_c::output_vt) - STAGE3_ERROR(0, lvalue, lvalue, "Assignment to FB output field variable are not be allowed."); + STAGE3_ERROR(0, lvalue, lvalue, "Assignment to FB output field variable is not be allowed."); } } } + /* No writing to CONSTANTs */ -void lvalue_check_c::check_constant_assignment(symbolic_variable_c *lvalue) { - unsigned int option = search_var_instance_decl->get_option(lvalue->var_name); +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 are not be allowed."); - } -} - -/* function_name(45) will check whether the first parameter of the function is not an output variable. */ -/* function_name(var_name) will check whether var_name is lvalue if the first parameter of the function is an output variable. */ -void lvalue_check_c::check_function_call_parameter(function_invocation_c *f_call) { - function_declaration_c *f_decl; - identifier_c *param_name; - symbol_c *call_param_value; - - if (NULL == f_call) - return; - /* We use called_function_declaration and for this reason LVALUE - * check must be run after DATA TYPE check + STAGE3_ERROR(0, lvalue, lvalue, "Assignment to CONSTANT variables is not be allowed."); + } +} + + +/* No assigning values to expressions. */ +void lvalue_check_c::check_assignment_to_expression(symbol_c *lvalue) { + /* TODO: check whether the lvalue is an expresion! */ + /* This may occur in function invocations, when passing values (possibly an expression) to one + * of the function's OUTPUT parameters. */ - if (NULL == f_call->called_function_declaration) - ERROR; - f_decl = (function_declaration_c *)f_call->called_function_declaration; - search_constant_type_c search_constant_type; +} + + + +void lvalue_check_c::verify_is_lvalue(symbol_c *lvalue) { + check_assignment_to_controlvar(lvalue); + check_assignment_to_output(lvalue); + check_assignment_to_constant(lvalue); + check_assignment_to_expression(lvalue); +} + + + + +/* check whether all values passed to OUT or IN_OUT parameters are legal lvalues. */ +void lvalue_check_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl) { + /* TODO */ +} + + +/* check whether all values passed to OUT or IN_OUT parameters are legal lvalues. */ +void lvalue_check_c::check_formal_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_name; + function_param_iterator_c fp_iterator(f_decl); function_call_param_iterator_c fcp_iterator(f_call); - function_param_iterator_c fp_iterator(f_decl); - do { - param_name = fp_iterator.next(); - if(param_name == NULL) return; - } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); - while((call_param_value = fcp_iterator.next_nf()) != NULL) { - if (search_constant_type.is_constant_value(call_param_value)) { - if (function_param_iterator_c::direction_out == fp_iterator.param_direction()) - STAGE3_ERROR(0, call_param_value, call_param_value, "Assignment Constant value to Output parameter are not be allowed."); + + /* Iterating through the formal parameters of the function call */ + while((call_param_name = fcp_iterator.next_f()) != NULL) { + + /* Obtaining the value being passed in the function call */ + symbol_c *call_param_value = fcp_iterator.get_current_value(); + if (NULL == call_param_value) ERROR; + + /* Find the corresponding parameter in function declaration, and it's direction (IN, OUT, IN_OUT) */ + identifier_c *param_name = fp_iterator.search(call_param_name); + function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); + + /* We only check if 'call_param_value' is a valid lvalue if the value is being passed + * to a valid paramater of the function being called, and that parameter is either OUT or IN_OUT. + */ + if ((param_name != NULL) && + ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction))) { + verify_is_lvalue(call_param_value); } - param_name = fp_iterator.next(); - } -} + } +} + + + + @@ -188,8 +225,12 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +// SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count; std::vector candidate_functions;) void *lvalue_check_c::visit(function_invocation_c *symbol) { - check_function_call_parameter(symbol); + if (NULL != symbol->formal_param_list) + check_formal_call(symbol, symbol->called_function_declaration); + if (NULL != symbol->nonformal_param_list) + check_nonformal_call(symbol, symbol->called_function_declaration); return NULL; } @@ -197,12 +238,7 @@ /* B 3.2.1 Assignment Statements */ /*********************************/ void *lvalue_check_c::visit(assignment_statement_c *symbol) { - symbolic_variable_c *lvalue; - - lvalue = (symbolic_variable_c *)symbol->l_exp; - check_for_controlvar_assignment(lvalue); - check_output_assignment(lvalue); - check_constant_assignment(lvalue); + verify_is_lvalue(symbol->l_exp); /* We call visit r_exp to check function_call */ symbol->r_exp->accept(*this); return NULL; diff -r dc6906338042 -r 35d391c38a30 stage3/lvalue_check.hh --- a/stage3/lvalue_check.hh Sat Apr 14 20:02:36 2012 +0200 +++ b/stage3/lvalue_check.hh Sun Apr 15 19:56:33 2012 +0100 @@ -44,17 +44,20 @@ class lvalue_check_c: public iterator_visitor_c { private: - search_varfb_instance_type_c *search_varfb_instance_type; - search_var_instance_decl_c *search_var_instance_decl; + search_varfb_instance_type_c *search_varfb_instance_type; + search_var_instance_decl_c *search_var_instance_decl; search_base_type_c search_base_type; int error_found; int current_display_error_level; std::vector control_variables; - symbol_c *base_type(symbol_c *symbol); - void check_for_controlvar_assignment(symbolic_variable_c *lvalue); - void check_output_assignment(symbolic_variable_c *lvalue); - void check_constant_assignment(symbolic_variable_c *lvalue); - void check_function_call_parameter(function_invocation_c *f_call); + + void verify_is_lvalue (symbol_c *lvalue); + void check_assignment_to_controlvar(symbol_c *lvalue); + void check_assignment_to_output (symbol_c *lvalue); + void check_assignment_to_constant (symbol_c *lvalue); + void check_assignment_to_expression(symbol_c *lvalue); + void check_formal_call (symbol_c *f_call, symbol_c *f_decl); + void check_nonformal_call(symbol_c *f_call, symbol_c *f_decl); public: