Fixing some bugs in lvalue checking (other bugs remain - to be fixed later)
authorMario de Sousa <msousa@fe.up.pt>
Sun, 15 Apr 2012 19:56:33 +0100
changeset 509 35d391c38a30
parent 508 dc6906338042
child 510 9317e04c1dde
Fixing some bugs in lvalue checking (other bugs remain - to be fixed later)
stage3/Makefile.in
stage3/lvalue_check.cc
stage3/lvalue_check.hh
--- 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@
--- 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 <strings.h>
 /* 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 <symbol_c *> 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;
--- 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 <symbol_c *> 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: