stage3/lvalue_check.cc
changeset 849 1f8885ae539a
parent 846 24d0be6c31f7
child 926 b8538c5d0aeb
equal deleted inserted replaced
823:c95f42f28b69 849:1f8885ae539a
   112 	/* Note that if symbol is pointing to an expression (or simply a literal value), it will return a NULL.
   112 	/* Note that if symbol is pointing to an expression (or simply a literal value), it will return a NULL.
   113 	 * Once we have implemented the check_assignment_to_expression() method, and abort calling the other checks (including this one)
   113 	 * Once we have implemented the check_assignment_to_expression() method, and abort calling the other checks (including this one)
   114 	 * when an expression is found, we may replace this check with an assertion...
   114 	 * when an expression is found, we may replace this check with an assertion...
   115 	 * if (NULL == struct_elem) ERROR;
   115 	 * if (NULL == struct_elem) ERROR;
   116 	 */
   116 	 */
   117 	symbol_c *struct_elem = decompose_lvalue.next_part();
   117 	symbol_c *struct_elem = decompose_lvalue.get_next();
   118 	if (NULL == struct_elem) return;
   118 	if (NULL == struct_elem) return;
   119 	
   119 	
   120 	symbol_c *type_decl   = search_var_instance_decl->get_decl(struct_elem);
   120 	symbol_c *type_decl   = search_var_instance_decl->get_decl(struct_elem);
   121 	// symbol_c *type_id  = spec_init_sperator_c::get_spec(type_decl); /* this is not required! search_base_type_c can handle spec_init symbols! */
   121 	// symbol_c *type_id  = spec_init_sperator_c::get_spec(type_decl); /* this is not required! search_base_type_c can handle spec_init symbols! */
   122 	symbol_c *basetype_id = search_base_type_c::get_basetype_id(/*type_id*/ type_decl);
   122 	symbol_c *basetype_id = search_base_type_c::get_basetype_id(/*type_id*/ type_decl);
   133 	 *       will be of FB type, which means we can quit this check!
   133 	 *       will be of FB type, which means we can quit this check!
   134 	 */
   134 	 */
   135 	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(basetype_id);
   135 	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(basetype_id);
   136 	if (function_block_type_symtable.end_value() == fb_decl) return;
   136 	if (function_block_type_symtable.end_value() == fb_decl) return;
   137 
   137 
   138 	while (NULL != (struct_elem = decompose_lvalue.next_part())) {
   138 	while (NULL != (struct_elem = decompose_lvalue.get_next())) {
   139 		search_var_instance_decl_c   fb_search_var_instance_decl(fb_decl);
   139 		search_var_instance_decl_c   fb_search_var_instance_decl(fb_decl);
   140 		if (search_var_instance_decl_c::output_vt == fb_search_var_instance_decl.get_vartype(struct_elem)) {
   140 		if (search_var_instance_decl_c::output_vt == fb_search_var_instance_decl.get_vartype(struct_elem)) {
   141 			STAGE3_ERROR(0, struct_elem, struct_elem, "Assignment to FB output variable is not allowed.");
   141 			STAGE3_ERROR(0, struct_elem, struct_elem, "Assignment to FB output variable is not allowed.");
   142 			return; /* no need to carry on checking once the first error is found! */
   142 			return; /* no need to carry on checking once the first error is found! */
   143 		}
   143 		}
   154 
   154 
   155 /*  No writing to CONSTANTs */
   155 /*  No writing to CONSTANTs */
   156 void lvalue_check_c::check_assignment_to_constant(symbol_c *lvalue) {
   156 void lvalue_check_c::check_assignment_to_constant(symbol_c *lvalue) {
   157 	unsigned int option = search_var_instance_decl->get_option(lvalue);
   157 	unsigned int option = search_var_instance_decl->get_option(lvalue);
   158 	if (option == search_var_instance_decl_c::constant_opt) {
   158 	if (option == search_var_instance_decl_c::constant_opt) {
   159 		STAGE3_ERROR(0, lvalue, lvalue, "Assignment to CONSTANT variables is not be allowed.");
   159 		STAGE3_ERROR(0, lvalue, lvalue, "Assignment to CONSTANT variables is not allowed.");
   160 	}
   160 	}
   161 }
   161 }
   162 
   162 
   163 
   163 
   164 /*  No assigning values to expressions. */
   164 /*  No assigning values to expressions. */
   165 void lvalue_check_c::check_assignment_to_expression(symbol_c *lvalue) {
   165 void lvalue_check_c::check_assignment_to_expression(symbol_c *lvalue) {
   166 	/* This may occur in function invocations, when passing values (possibly an expression) to one 
       
   167 	 * of the function's OUTPUT or IN_OUT parameters.
       
   168 	 */
       
   169 	/* This may occur in function invocations, when passing values (possibly an expression) to one
   166 	/* This may occur in function invocations, when passing values (possibly an expression) to one
   170 	 * of the function's OUTPUT or IN_OUT parameters.
   167 	 * of the function's OUTPUT or IN_OUT parameters.
   171 	 */
   168 	 */
   172 	if ( 
   169 	if ( 
   173 	     /*********************/
   170 	     /*********************/
   231 	     (typeid( *lvalue ) == typeid( mod_expression_c               )) ||
   228 	     (typeid( *lvalue ) == typeid( mod_expression_c               )) ||
   232 	     (typeid( *lvalue ) == typeid( power_expression_c             )) ||
   229 	     (typeid( *lvalue ) == typeid( power_expression_c             )) ||
   233 	     (typeid( *lvalue ) == typeid( neg_expression_c               )) ||
   230 	     (typeid( *lvalue ) == typeid( neg_expression_c               )) ||
   234 	     (typeid( *lvalue ) == typeid( not_expression_c               )) ||
   231 	     (typeid( *lvalue ) == typeid( not_expression_c               )) ||
   235 	     (typeid( *lvalue ) == typeid( function_invocation_c          )))
   232 	     (typeid( *lvalue ) == typeid( function_invocation_c          )))
   236 		STAGE3_ERROR(0, lvalue, lvalue, "Assigning an expression to an OUT or IN_OUT parameter is not allowed.");
   233 		STAGE3_ERROR(0, lvalue, lvalue, "Assignment to an expression or a literal value is not allowed.");
   237 }                                                                  
   234 }                                                                  
   238 
   235 
   239 
   236 
   240 
   237 
       
   238 /*  No assigning values to IL lists. */
       
   239 void lvalue_check_c::check_assignment_to_il_list(symbol_c *lvalue) {
       
   240 	/* This may occur in formal invocations in IL, where an embedded IL list may be used instead of a symbolic_variable
       
   241 	 * when passing an IN_OUT parameter! Note that it will never occur to OUT parameters, as the syntax does not allow it,
       
   242 	 * although this does not affect out algorithm here!
       
   243 	 */
       
   244 	if ( 
       
   245 	     /****************************************/
       
   246 	     /* B.2 - Language IL (Instruction List) */
       
   247 	     /****************************************/
       
   248 	     /***********************************/
       
   249 	     /* B 2.1 Instructions and Operands */
       
   250 	     /***********************************/
       
   251 	     (typeid( *lvalue ) == typeid( simple_instr_list_c)))
       
   252 		STAGE3_ERROR(0, lvalue, lvalue, "Assigning an IL list to an IN_OUT parameter is not allowed.");
       
   253 }                                                                  
   241 
   254 
   242 
   255 
   243 
   256 
   244 
   257 
   245 void lvalue_check_c::verify_is_lvalue(symbol_c *lvalue) {
   258 void lvalue_check_c::verify_is_lvalue(symbol_c *lvalue) {
       
   259 	if (NULL == lvalue) return; // missing operand in source code being compiled. Error will be caught and reported by datatype checking!
   246 	int init_error_count = error_count;  /* stop the checks once an error has been found... */
   260 	int init_error_count = error_count;  /* stop the checks once an error has been found... */
   247 	if (error_count == init_error_count)  check_assignment_to_expression(lvalue);
   261 	if (error_count == init_error_count)  check_assignment_to_expression(lvalue);
       
   262 	if (error_count == init_error_count)  check_assignment_to_il_list   (lvalue);
   248 	if (error_count == init_error_count)  check_assignment_to_controlvar(lvalue);
   263 	if (error_count == init_error_count)  check_assignment_to_controlvar(lvalue);
   249 	if (error_count == init_error_count)  check_assignment_to_output(lvalue);
   264 	if (error_count == init_error_count)  check_assignment_to_output    (lvalue);
   250 	if (error_count == init_error_count)  check_assignment_to_constant(lvalue);
   265 	if (error_count == init_error_count)  check_assignment_to_constant  (lvalue);
   251 }
   266 }
   252 
   267 
   253 
   268 
   254 
   269 
   255 
   270 
   259  * This means that, for non formal function calls in IL, de current (default value) must be artificially added to the
   274  * This means that, for non formal function calls in IL, de current (default value) must be artificially added to the
   260  * beginning of the parameter list BEFORE calling handle_function_call().
   275  * beginning of the parameter list BEFORE calling handle_function_call().
   261  */
   276  */
   262 #include <string.h> /* required for strcmp() */
   277 #include <string.h> /* required for strcmp() */
   263 void lvalue_check_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl) {
   278 void lvalue_check_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl) {
       
   279 	/* if data type semantic verification was unable to determine which function is being called,
       
   280 	 * then it does not make sense to go ahead and check for lvalues to unknown parameters.
       
   281 	 * We simply bug out!
       
   282 	 */
       
   283 	if (NULL == f_decl) return;
       
   284 	
   264 	symbol_c *call_param_value;
   285 	symbol_c *call_param_value;
   265 	identifier_c *param_name;
   286 	identifier_c *param_name;
   266 	function_param_iterator_c       fp_iterator(f_decl);
   287 	function_param_iterator_c       fp_iterator(f_decl);
   267 	function_call_param_iterator_c fcp_iterator(f_call);
   288 	function_call_param_iterator_c fcp_iterator(f_call);
   268 
   289 
   284 		/* We only process the parameter value if the paramater itself is valid... */
   305 		/* We only process the parameter value if the paramater itself is valid... */
   285 		if (param_name != NULL) {
   306 		if (param_name != NULL) {
   286 			/* If the parameter is either OUT or IN_OUT, we check if 'call_param_value' is a valid lvalue */
   307 			/* If the parameter is either OUT or IN_OUT, we check if 'call_param_value' is a valid lvalue */
   287 			if ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction)) 
   308 			if ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction)) 
   288 				verify_is_lvalue(call_param_value);
   309 				verify_is_lvalue(call_param_value);
   289 			/* parameter values to IN parameters may be expressions with function invocations that must also be checked! */
   310 			/* parameter values to IN  parameters may be expressions with function invocations that must also be checked! */
   290 			if (function_param_iterator_c::direction_in == param_direction) 
   311 			/* parameter values to OUT or IN_OUT parameters may contain arrays, whose subscripts contain expressions that must be checked! */
   291 				call_param_value->accept(*this);  
   312 			call_param_value->accept(*this);  
   292 		}
   313 		}
   293 	}
   314 	}
   294 }
   315 }
   295 
   316 
   296 
   317 
   324 		/* We only process the parameter value if the paramater itself is valid... */
   345 		/* We only process the parameter value if the paramater itself is valid... */
   325 		if (param_name != NULL) {
   346 		if (param_name != NULL) {
   326 			/* If the parameter is either OUT or IN_OUT, we check if 'call_param_value' is a valid lvalue */
   347 			/* If the parameter is either OUT or IN_OUT, we check if 'call_param_value' is a valid lvalue */
   327 			if ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction)) 
   348 			if ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction)) 
   328 				verify_is_lvalue(call_param_value);
   349 				verify_is_lvalue(call_param_value);
   329 			/* parameter values to IN parameters may be expressions with function invocations that must also be checked! */
   350 			/* parameter values to IN  parameters may be expressions with function invocations that must also be checked! */
   330 			if (function_param_iterator_c::direction_in == param_direction) 
   351 			/* parameter values to OUT or IN_OUT parameters may contain arrays, whose subscripts contain expressions that must be checked! */
   331 				call_param_value->accept(*this);  
   352 			call_param_value->accept(*this);  
   332 		
       
   333  		}
   353  		}
   334 	}
   354 	}
   335 }
   355 }
   336 
   356 
   337 
   357