stage3/lvalue_check.cc
changeset 510 9317e04c1dde
parent 509 35d391c38a30
child 512 f915ab676d7e
equal deleted inserted replaced
509:35d391c38a30 510:9317e04c1dde
    42     fprintf(stderr, "%s:%d-%d..%d-%d: error: ",                                                                             \
    42     fprintf(stderr, "%s:%d-%d..%d-%d: error: ",                                                                             \
    43             FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
    43             FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
    44                                                  LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column);\
    44                                                  LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column);\
    45     fprintf(stderr, __VA_ARGS__);                                                                                           \
    45     fprintf(stderr, __VA_ARGS__);                                                                                           \
    46     fprintf(stderr, "\n");                                                                                                  \
    46     fprintf(stderr, "\n");                                                                                                  \
    47     error_found = true;                                                                                                     \
    47     error_count++;                                                                                                     \
    48   }                                                                                                                         \
    48   }                                                                                                                         \
    49 }
    49 }
    50 
    50 
    51 
    51 
    52 #define STAGE3_WARNING(symbol1, symbol2, ...) {                                                                             \
    52 #define STAGE3_WARNING(symbol1, symbol2, ...) {                                                                             \
    58     warning_found = true;                                                                                                   \
    58     warning_found = true;                                                                                                   \
    59 }
    59 }
    60 
    60 
    61 
    61 
    62 lvalue_check_c::lvalue_check_c(symbol_c *ignore) {
    62 lvalue_check_c::lvalue_check_c(symbol_c *ignore) {
    63 	error_found = false;
    63 	error_count = 0;
    64 }
    64 }
    65 
    65 
    66 lvalue_check_c::~lvalue_check_c(void) {
    66 lvalue_check_c::~lvalue_check_c(void) {
    67 }
    67 }
    68 
    68 
    69 int lvalue_check_c::get_error_found() {
    69 int lvalue_check_c::get_error_count() {
    70 	return error_found;
    70 	return error_count;
    71 }
    71 }
    72 
    72 
    73 
    73 
    74 #include <strings.h>
    74 #include <strings.h>
    75 /* No writing to iterator variables (used in FOR loops) inside the loop itself */
    75 /* No writing to iterator variables (used in FOR loops) inside the loop itself */
    82 		}
    82 		}
    83 	}
    83 	}
    84 }
    84 }
    85 
    85 
    86 
    86 
    87 /* fb_instance.var := ...  is not valid if var is output (not input ??) variable */
    87 /* fb_instance.var := ...  is not valid if var is output variable */
    88 void lvalue_check_c::check_assignment_to_output(symbol_c * lvalue) {
    88 /* NOTE, if a fb_instance1.fb_instance2.fb_instance3.var is used, we must iteratively check that none of the 
    89 	symbol_c *type_id = search_varfb_instance_type->get_basetype_id(lvalue);
    89  *       FB records are declared as OUTPUT variables!!  
    90 	if (NULL != type_id) {
    90  *       This is the reason why we have the while() loop in this function!
    91 		function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(type_id);
    91  */
    92 		if (function_block_type_symtable.end_value() != fb_decl) {
    92 void lvalue_check_c::check_assignment_to_output(symbol_c *lvalue) {
    93 			search_var_instance_decl_c   search_var_instance_decl(fb_decl);
    93 	decompose_var_instance_name_c decompose_lvalue(lvalue);
    94 			structured_variable_c * str_var = (structured_variable_c *)lvalue;
    94 	search_base_type_c            search_base_type;
    95 			unsigned int vartype = search_var_instance_decl.get_vartype(str_var->field_selector);
    95 
    96 			if (vartype == search_var_instance_decl_c::output_vt)
    96 	symbol_c *struct_elem = decompose_lvalue.next_part();
    97 				STAGE3_ERROR(0, lvalue, lvalue, "Assignment to FB output field variable is not be allowed.");
    97 	symbol_c *type_decl   = search_var_instance_decl->get_decl(struct_elem);
       
    98 	// 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! */
       
    99 	symbol_c *basetype_id = search_base_type.get_basetype_id(/*type_id*/ type_decl);
       
   100 	/* If we can not determine the data type of the element, then the code must have a data type semantic error.
       
   101 	 * This will have been caught by the data type semantic verifier, so we do not bother with this anymore!
       
   102 	 */
       
   103 	if (NULL == basetype_id) return;
       
   104 
       
   105 	/* Determine if the record/structure element is of a FB type. */
       
   106 	/* NOTE: If the structure element is not a FB type, then we can quit this check.
       
   107 	 *       Remember that the standard does not allow a STRUCT data type to have elements that are FB instances!
       
   108 	 *       Similarly, arrays of FB instances is also not allowed.
       
   109 	 *       So, as soon as we find one record/structure element that is not a FB, no other record/structure element
       
   110 	 *       will be of FB type, which means we can quit this check!
       
   111 	 */
       
   112 	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(basetype_id);
       
   113 	if (function_block_type_symtable.end_value() == fb_decl) return;
       
   114 
       
   115 	while (NULL != (struct_elem = decompose_lvalue.next_part())) {
       
   116 		search_var_instance_decl_c   fb_search_var_instance_decl(fb_decl);
       
   117 		if (search_var_instance_decl_c::output_vt == fb_search_var_instance_decl.get_vartype(struct_elem)) {
       
   118 			STAGE3_ERROR(0, struct_elem, struct_elem, "Assignment to FB output variable is not allowed.");
       
   119 			return; /* no need to carry on checking once the first error is found! */
    98 		}
   120 		}
       
   121 
       
   122 		/* prepare for any possible further record/structure elements */
       
   123 		type_decl   = fb_search_var_instance_decl.get_decl(struct_elem);
       
   124 		basetype_id = search_base_type.get_basetype_id(type_decl);
       
   125 		if (NULL == basetype_id) return; /* same comment as above... */
       
   126 		fb_decl = function_block_type_symtable.find_value(basetype_id);
       
   127 		if (function_block_type_symtable.end_value() == fb_decl) return; /* same comment as above... */
    99 	}
   128 	}
   100 }
   129 }
   101 
   130 
   102 
   131 
   103 /*  No writing to CONSTANTs */
   132 /*  No writing to CONSTANTs */
   111 
   140 
   112 /*  No assigning values to expressions. */
   141 /*  No assigning values to expressions. */
   113 void lvalue_check_c::check_assignment_to_expression(symbol_c *lvalue) {
   142 void lvalue_check_c::check_assignment_to_expression(symbol_c *lvalue) {
   114 	/* TODO: check whether the lvalue is an expresion! */
   143 	/* TODO: check whether the lvalue is an expresion! */
   115 	/* This may occur in function invocations, when passing values (possibly an expression) to one 
   144 	/* This may occur in function invocations, when passing values (possibly an expression) to one 
   116 	 * of the function's OUTPUT parameters.
   145 	 * of the function's OUTPUT or IN_OUT parameters.
   117 	 */
   146 	 */
   118 }
   147 }
   119 
   148 
   120 
   149 
   121 
   150 
   122 void lvalue_check_c::verify_is_lvalue(symbol_c *lvalue) {
   151 void lvalue_check_c::verify_is_lvalue(symbol_c *lvalue) {
       
   152 	check_assignment_to_expression(lvalue);
   123 	check_assignment_to_controlvar(lvalue);
   153 	check_assignment_to_controlvar(lvalue);
   124 	check_assignment_to_output(lvalue);
   154 	check_assignment_to_output(lvalue);
   125 	check_assignment_to_constant(lvalue);
   155 	check_assignment_to_constant(lvalue);
   126 	check_assignment_to_expression(lvalue);
       
   127 }
   156 }
   128 
   157 
   129 
   158 
   130 
   159 
   131 
   160 
   159 		function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
   188 		function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
   160 		
   189 		
   161 		/* We only check if 'call_param_value' is a valid lvalue if the value is being passed
   190 		/* We only check if 'call_param_value' is a valid lvalue if the value is being passed
   162 		 * to a valid paramater of the function being called, and that parameter is either OUT or IN_OUT.
   191 		 * to a valid paramater of the function being called, and that parameter is either OUT or IN_OUT.
   163 		 */
   192 		 */
   164 		if ((param_name != NULL) && 
   193 		if ((param_name != NULL) && ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction))) {
   165 		    ((function_param_iterator_c::direction_out == param_direction) || (function_param_iterator_c::direction_inout == param_direction))) {
       
   166 			verify_is_lvalue(call_param_value);
   194 			verify_is_lvalue(call_param_value);
   167 		}
   195 		}
   168 	}
   196 	}
   169 }
   197 }
   170 
   198 
   225 /***********************/
   253 /***********************/
   226 /* B 3.1 - Expressions */
   254 /* B 3.1 - Expressions */
   227 /***********************/
   255 /***********************/
   228 // SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count; std::vector <symbol_c *> candidate_functions;)
   256 // SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count; std::vector <symbol_c *> candidate_functions;)
   229 void *lvalue_check_c::visit(function_invocation_c *symbol) {
   257 void *lvalue_check_c::visit(function_invocation_c *symbol) {
   230 	if (NULL != symbol->formal_param_list)
   258 	if (NULL != symbol->formal_param_list   )  check_formal_call   (symbol, symbol->called_function_declaration);
   231 		check_formal_call(symbol, symbol->called_function_declaration);
   259 	if (NULL != symbol->nonformal_param_list)  check_nonformal_call(symbol, symbol->called_function_declaration);
   232 	if (NULL != symbol->nonformal_param_list)
       
   233 		check_nonformal_call(symbol, symbol->called_function_declaration);
       
   234 	return NULL;
   260 	return NULL;
   235 }
   261 }
   236 
   262 
   237 /*********************************/
   263 /*********************************/
   238 /* B 3.2.1 Assignment Statements */
   264 /* B 3.2.1 Assignment Statements */