Do datatype checking of initial values for structures and FBs, and print error messages when compiling erroneuos source code.
authorMario de Sousa <msousa@fe.up.pt>
Wed, 05 Apr 2017 13:21:50 +0100
changeset 1047 34b733cb6641
parent 1046 292b7dcf14f6
child 1048 37966f855bed
Do datatype checking of initial values for structures and FBs, and print error messages when compiling erroneuos source code.
stage3/fill_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.cc
stage3/print_datatypes_error.cc
stage3/print_datatypes_error.hh
--- a/stage3/fill_candidate_datatypes.cc	Tue Apr 04 17:21:42 2017 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Wed Apr 05 13:21:50 2017 +0100
@@ -1176,21 +1176,28 @@
 	iterator_visitor_c::visit(symbol); // call visit(structure_element_initialization_c *) on all elements
 
 	for (unsigned int i = 0; i < symbol->parent->candidate_datatypes.size(); i++) { // size() should always be 1 here -> a single structure or FB type!
-		// assume symbol->parent is a FB type
+		// assume symbol->parent->candidate_datatypes[i] is a FB type
 		search_varfb_instance_type_c search_varfb_instance_type(symbol->parent->candidate_datatypes[i]);
+		// assume symbol->parent->candidate_datatypes[i] is a STRUCT data type
+		structure_element_declaration_list_c *struct_decl = dynamic_cast<structure_element_declaration_list_c *>(symbol->parent->candidate_datatypes[i]);
 		// flag indicating all struct_elem->structure_element_name are structure elements found in the symbol->parent->candidate_datatypes[i] datatype
 		int flag_all_elem_ok = 1; // assume all found
 		for (int k = 0; k < symbol->n; k++) {
-			// assume symbol->parent->candidate_datatypes[i] is a FB type...
-			structure_element_initialization_c *struct_elem = (structure_element_initialization_c *)symbol->get_element(k);
-			symbol_c *type = search_varfb_instance_type.get_basetype_decl(struct_elem->structure_element_name);
-			if (!get_datatype_info_c::is_type_valid(type)) {
-				// either get_datatype_info_c::is_type_valid(type) is not a FB type, or the element is not declared in that FB
-				// Lets try a struct type!!
-				// TODO...
+			structure_element_initialization_c *struct_elem = dynamic_cast<structure_element_initialization_c *>(symbol->get_element(k));
+			if (struct_elem == NULL) ERROR;
+			
+			// assume symbol->parent is a FB type...
+			symbol_c *type = NULL;
+			if (struct_decl != NULL) {
+				// search in the struct!!
+				type = search_base_type_c::get_basetype_decl(struct_decl->find_element(struct_elem->structure_element_name));
+			} else {
+				// parent is a FB type. Lets search there!!
+				type = search_varfb_instance_type.get_basetype_decl(struct_elem->structure_element_name);
 			}
 			if (!get_datatype_info_c::is_ANY_ELEMENTARY(type) && get_datatype_info_c::is_type_valid(type)) {
-				add_datatype_to_candidate_list(struct_elem, type); // for non-elementary datatypes, we must use a top->down algorithm!!
+				// for non-elementary datatypes, we must use a top->down algorithm!!
+				add_datatype_to_candidate_list(struct_elem, type); 
 				struct_elem->accept(*this);
 			}
 			if (search_in_candidate_datatype_list(type, struct_elem->candidate_datatypes) < 0) {
--- a/stage3/narrow_candidate_datatypes.cc	Tue Apr 04 17:21:42 2017 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Wed Apr 05 13:21:50 2017 +0100
@@ -673,20 +673,36 @@
 /* structure_element_initialization_list ',' structure_element_initialization */
 // SYM_LIST(structure_element_initialization_list_c)
 void *narrow_candidate_datatypes_c::visit(structure_element_initialization_list_c *symbol) {
-	if (get_datatype_info_c::is_type_valid(symbol->datatype)) {
-		/* Note that in principle structure_element_initialization_list_c will have at most 1 candidate_datatype
-		 * (the FB or structure in the type specification). However, our algorithm is more generic and will
-		 * assume that more than 1 candidate_datatype is possible. In this case we need to iterate and check each
-		 * candidate_datatype whether it is feasible, as they may all be feasible but not for the same ...
-		 */
-		// assume symbol->datatype is a FB type
-		search_varfb_instance_type_c search_varfb_instance_type(symbol->datatype);
+	symbol_c *type = NULL;
+
+	 // first try to narrow with the correct type, if valid.
+	if (!get_datatype_info_c::is_type_valid(type)) type = symbol->datatype;
+	 // to reduce number of error messages, we try to narrow with parent's spec_init->datatype
+	if (!get_datatype_info_c::is_type_valid(type)) type = symbol->parent->datatype;
+
+	if (get_datatype_info_c::is_type_valid(type)) {
+		// We need to iterate and determine the required datatype of each structure element
+		// assume type is a FB type
+		search_varfb_instance_type_c search_varfb_instance_type(type);
+		// assume type is a STRUCT type
+		structure_element_declaration_list_c *struct_decl = dynamic_cast<structure_element_declaration_list_c *>(type);
 		for (int k = 0; k < symbol->n; k++) {
 			structure_element_initialization_c *struct_elem = (structure_element_initialization_c *)symbol->get_element(k);
-			symbol_c *type = search_varfb_instance_type.get_basetype_decl(struct_elem->structure_element_name);
+			symbol_c *type = NULL;
+			if (struct_decl == NULL) {
+				// type is not a struct. Must be a FB.
+				type = search_varfb_instance_type.get_basetype_decl(struct_elem->structure_element_name);
+			} else {
+				// type is a struct.
+				type = search_base_type_c::get_basetype_decl(struct_decl->find_element(struct_elem->structure_element_name));
+			}
 			set_datatype(type, struct_elem);
 			struct_elem->accept(*this);
-			if (struct_elem->datatype == NULL) ERROR; // should never occur. Already checked in fill_candidate_datatypes_c
+			/* We do best effort narrowing, even in the presence of errors, to reduce number of error messages
+			 * so the following two assertions are not always met.
+			 */
+			// if (!get_datatype_info_c::is_type_valid(type)) ERROR;  
+			// if (struct_elem->datatype == NULL) ERROR; // should never occur. Already checked in fill_candidate_datatypes_c
 		}
 	}
 	return NULL;
@@ -694,7 +710,7 @@
 
 /*  structure_element_name ASSIGN value */
 // SYM_REF2(structure_element_initialization_c, structure_element_name, value)
-void *narrow_candidate_datatypes_c::visit(structure_element_initialization_c *symbol) {set_datatype(symbol->datatype, symbol->value); return NULL;}
+void *narrow_candidate_datatypes_c::visit(structure_element_initialization_c *symbol) {set_datatype(symbol->datatype, symbol->value); symbol->value->accept(*this); return NULL;}
 
 /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
 // SYM_REF4(string_type_declaration_c, string_type_name, elementary_string_type_name, string_type_declaration_size, string_type_declaration_init/* may be == NULL! */) 
--- a/stage3/print_datatypes_error.cc	Tue Apr 04 17:21:42 2017 +0100
+++ b/stage3/print_datatypes_error.cc	Wed Apr 05 13:21:50 2017 +0100
@@ -545,6 +545,16 @@
 }
 
 
+
+void *print_datatypes_error_c::visit(structure_element_initialization_c *symbol) {
+	symbol->value->accept(*this);
+	if (!get_datatype_info_c::is_type_valid(symbol->datatype))
+		STAGE3_ERROR(0, symbol, symbol, "Initialization element identifier (%s) is not declared in referenced structure/FB scope, or is set to value of incompatible datatype.", 
+			                        symbol->structure_element_name->token->value);
+	return NULL;
+}
+
+    
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
--- a/stage3/print_datatypes_error.hh	Tue Apr 04 17:21:42 2017 +0100
+++ b/stage3/print_datatypes_error.hh	Wed Apr 05 13:21:50 2017 +0100
@@ -161,6 +161,8 @@
     void *visit(simple_spec_init_c *symbol);
 //  void *visit(data_type_declaration_c *symbol); /* use base iterator_c method! */
     void *visit(enumerated_value_c *symbol);
+//  void *visit(structure_element_initialization_list_c *symbol);
+    void *visit(structure_element_initialization_c *symbol);
 
     /*********************/
     /* B 1.4 - Variables */