Better identification of erros in function/FB invocations.
authorMario de Sousa <msousa@fe.up.pt>
Sun, 05 Feb 2012 19:09:12 +0000
changeset 426 78f31e12fc52
parent 425 c8e6cf57324a
child 427 eb9bc99944d9
Better identification of erros in function/FB invocations.
absyntax_utils/function_param_iterator.cc
stage3/fill_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.cc
stage3/print_datatypes_error.cc
--- a/absyntax_utils/function_param_iterator.cc	Fri Feb 03 18:16:20 2012 +0000
+++ b/absyntax_utils/function_param_iterator.cc	Sun Feb 05 19:09:12 2012 +0000
@@ -225,7 +225,8 @@
   function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(pou_decl);
   program_declaration_c        * p_decl = dynamic_cast<program_declaration_c        *>(pou_decl);
 
-  if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) ERROR;
+  if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) 
+    ERROR;
 
   /* OK. Now initialise this object... */
   this->f_decl = pou_decl;
--- a/stage3/fill_candidate_datatypes.cc	Fri Feb 03 18:16:20 2012 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Sun Feb 05 19:09:12 2012 +0000
@@ -1692,7 +1692,22 @@
 
 	/* Look for all compatible function declarations, and add their return datatypes 
 	 * to the candidate_datatype list of this function invocation. 
+	 *
+	 * If only one function exists, we add its return datatype to the candidate_datatype list,
+	 * even if the parameters passed to it are invalid.
+	 * This guarantees that the remainder of the expression in which the function call is inserted
+	 * is treated as if the function call returns correctly, and therefore does not generate
+	 * spurious error messages.
+	 * Even if the parameters to the function call are invalid, doing this is still safe, as the 
+	 * expressions inside the function call will themselves have erros and will  guarantee that 
+	 * compilation is aborted in stage3.
 	 */
+	if (function_symtable.multiplicity(symbol->function_name) == 1) {
+		f_decl = function_symtable.get_value(lower);
+		returned_parameter_type = base_type(f_decl->type_name);
+		symbol->candidate_functions.push_back(f_decl);
+		symbol->candidate_datatypes.push_back(returned_parameter_type);
+	}
 	for(; lower != upper; lower++) {
 		bool compatible = false;
 		
--- a/stage3/narrow_candidate_datatypes.cc	Fri Feb 03 18:16:20 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Sun Feb 05 19:09:12 2012 +0000
@@ -141,7 +141,6 @@
 	unsigned int i;
 
 	if (NULL != ext_parm_count) *ext_parm_count = -1;
-
 	/* Iterating through the formal parameters of the function call */
 	while((call_param_name = fcp_iterator.next_f()) != NULL) {
 
@@ -1025,6 +1024,7 @@
 
 	/* set the called_function_declaration. */
 	symbol->called_function_declaration = NULL;
+#if 0
 	if (symbol->candidate_datatypes.size() == 1) {
 		/* If only one possible called function, then that is the function to call!
 		 * In this case we ignore the symbol->datatype value (that may even be NULL).
@@ -1037,10 +1037,10 @@
 		symbol->called_function_declaration = symbol->candidate_functions[0];
 		if ((NULL != symbol->datatype) && (!is_type_equal(symbol->candidate_datatypes[0], symbol->datatype)))
 			ERROR;
-	}
-	else {
+	} else
+#endif	
+	{
 		/* set the called_function_declaration taking into account the datatype that we need to return */
-		symbol->called_function_declaration = NULL;
 		for(unsigned int i = 0; i < symbol->candidate_datatypes.size(); i++) {
 			if (is_type_equal(symbol->candidate_datatypes[i], symbol->datatype)) {
 				symbol->called_function_declaration = symbol->candidate_functions[i];
@@ -1052,10 +1052,27 @@
 	 *       necessarily an internal compiler error. It could be because the symbol->datatype is NULL
 	 *       (because the ST code being analysed has an error _before_ this function invocation).
 	 *       However, we don't just give, up, we carry on recursivly analysing the code, so as to be
-	 *       able to print out any error messages related to underlying code that could be partially correct.
+	 *       able to print out any error messages related to the parameters being passed in this function 
+	 *       invocation.
 	 */
 	/* if (NULL == symbol->called_function_declaration) ERROR; */
-	
+
+	if (symbol->candidate_datatypes.size() == 1) {
+		/* If only one function declaration, then we use that (even if symbol->datatypes == NULL)
+		 * so we can check for errors in the expressions used to pass parameters in this
+		 * function invocation.
+		 */
+		symbol->called_function_declaration = symbol->candidate_functions[0];
+	}
+	/* If an overloaded function is being invoked, and we cannot determine which version to use,
+	 * then we can not meaningfully verify the expressions used inside that function invocation.
+	 * We simply give up!
+	 */
+	if (NULL == symbol->called_function_declaration) {
+printf("giving up!\n");
+		return NULL;
+	}
+
 	if (NULL != symbol->nonformal_param_list)  narrow_nonformal_call(symbol, symbol->called_function_declaration, &ext_parm_count);
 	if (NULL != symbol->   formal_param_list)     narrow_formal_call(symbol, symbol->called_function_declaration, &ext_parm_count);
 	symbol->extensible_param_count = ext_parm_count;
--- a/stage3/print_datatypes_error.cc	Fri Feb 03 18:16:20 2012 +0000
+++ b/stage3/print_datatypes_error.cc	Sun Feb 05 19:09:12 2012 +0000
@@ -470,8 +470,6 @@
 }
 
 void *print_datatypes_error_c::visit(LDN_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -481,7 +479,6 @@
 }
 
 void *print_datatypes_error_c::visit(ST_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
 	/* MANU:
 	 * if prev_instruction is NULL we can print a message error or warning error like:
 	 * we can't use a ST like first instruction.
@@ -496,7 +493,6 @@
 }
 
 void *print_datatypes_error_c::visit(STN_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
 	/* MANU:
 	 * if prev_instruction is NULL we can print a message error or warning error like:
 	 * we can't use a ST like first instruction.
@@ -516,8 +512,6 @@
 }
 
 void *print_datatypes_error_c::visit(S_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -527,8 +521,6 @@
 }
 
 void *print_datatypes_error_c::visit(R_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -538,8 +530,6 @@
 }
 
 void *print_datatypes_error_c::visit(S1_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -549,8 +539,6 @@
 }
 
 void *print_datatypes_error_c::visit(R1_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -590,8 +578,6 @@
 }
 
 void *print_datatypes_error_c::visit(AND_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -601,8 +587,6 @@
 }
 
 void *print_datatypes_error_c::visit(OR_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -612,8 +596,6 @@
 }
 
 void *print_datatypes_error_c::visit(XOR_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -623,8 +605,6 @@
 }
 
 void *print_datatypes_error_c::visit(ANDN_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -634,8 +614,6 @@
 }
 
 void *print_datatypes_error_c::visit(ORN_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -645,8 +623,6 @@
 }
 
 void *print_datatypes_error_c::visit(XORN_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -656,8 +632,6 @@
 }
 
 void *print_datatypes_error_c::visit(ADD_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -667,8 +641,6 @@
 }
 
 void *print_datatypes_error_c::visit(SUB_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -678,8 +650,6 @@
 }
 
 void *print_datatypes_error_c::visit(MUL_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -689,8 +659,6 @@
 }
 
 void *print_datatypes_error_c::visit(DIV_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -700,8 +668,6 @@
 }
 
 void *print_datatypes_error_c::visit(MOD_operator_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	il_operand->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
 		(il_operand->candidate_datatypes.size() > 0))
@@ -798,8 +764,6 @@
 /***********************/
 
 void *print_datatypes_error_c::visit(or_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -811,8 +775,6 @@
 
 
 void *print_datatypes_error_c::visit(xor_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -824,8 +786,6 @@
 
 
 void *print_datatypes_error_c::visit(and_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -837,8 +797,6 @@
 
 
 void *print_datatypes_error_c::visit(equ_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -850,8 +808,6 @@
 
 
 void *print_datatypes_error_c::visit(notequ_expression_c *symbol)  {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -863,8 +819,6 @@
 
 
 void *print_datatypes_error_c::visit(lt_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -876,8 +830,6 @@
 
 
 void *print_datatypes_error_c::visit(gt_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -889,8 +841,6 @@
 
 
 void *print_datatypes_error_c::visit(le_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -902,8 +852,6 @@
 
 
 void *print_datatypes_error_c::visit(ge_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -915,14 +863,12 @@
 
 
 void *print_datatypes_error_c::visit(add_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
-		(symbol->r_exp->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(symbol, symbol, "Current '+' result and operand not of same data type.");
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '+' expression.");
 
 	return NULL;
 }
@@ -930,58 +876,48 @@
 
 
 void *print_datatypes_error_c::visit(sub_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
-		(symbol->r_exp->candidate_datatypes.size() > 0))
-			STAGE3_ERROR(symbol, symbol, "Current '-' result and operand not of same data type.");
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+			STAGE3_ERROR(symbol, symbol, "Data type mismatch for '-' expression.");
 	return NULL;
 }
 
 void *print_datatypes_error_c::visit(mul_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
-		(symbol->r_exp->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(symbol, symbol, "Current '*' result and operand not of same data type.");
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '*' expression.");
 	return NULL;
 }
 
 void *print_datatypes_error_c::visit(div_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
-		(symbol->r_exp->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(symbol, symbol, "Current '/' result and operand not of same data type.");
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '/' expression.");
 	return NULL;
 }
 
 
 void *print_datatypes_error_c::visit(mod_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
-		(symbol->r_exp->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(symbol, symbol, "Current 'MOD' result and operand not of same data type.");
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MOD' expression.");
 	return NULL;
 }
 
 
 void *print_datatypes_error_c::visit(power_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0) 		&&
@@ -993,8 +929,6 @@
 
 
 void *print_datatypes_error_c::visit(neg_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0)      &&
 		(symbol->exp->candidate_datatypes.size() > 0))
@@ -1004,8 +938,6 @@
 
 
 void *print_datatypes_error_c::visit(not_expression_c *symbol) {
-	if (NULL != symbol->datatype) return NULL;
-
 	symbol->exp->accept(*this);
 	if ((symbol->candidate_datatypes.size() == 0)      &&
 		(symbol->exp->candidate_datatypes.size() > 0))
@@ -1015,27 +947,35 @@
 
 
 void *print_datatypes_error_c::visit(function_invocation_c *symbol) {
-	list_c *parameter_list;
-
-	if (NULL != symbol->formal_param_list)
-		parameter_list = (list_c *)symbol->formal_param_list;
-	else if (NULL != symbol->nonformal_param_list)
-		parameter_list = (list_c *)symbol->nonformal_param_list;
-	else ERROR;
-
-	parameter_list->accept(*this);
-
-	if (symbol->candidate_datatypes.size() == 0) {
+	symbol_c *param_value, *param_name;
+	function_call_param_iterator_c fcp_iterator(symbol);
+	bool function_invocation_error = false;
+
+	if ((NULL != symbol->formal_param_list) && (NULL != symbol->nonformal_param_list)) 
+		ERROR;
+
+	if (NULL != symbol->formal_param_list) {
+		symbol->formal_param_list->accept(*this);
+		while ((param_name = fcp_iterator.next_f()) != NULL) {
+			param_value = fcp_iterator.get_current_value();
+			if (NULL == param_value->datatype) {
+				function_invocation_error = true;
+			}
+		}
+	}
+	if (NULL != symbol->nonformal_param_list) {
+		symbol->nonformal_param_list->accept(*this);
+		while ((param_value = fcp_iterator.next_nf()) != NULL) {
+			if (NULL == param_value->datatype) {
+				function_invocation_error = true;
+			}
+		}
+	}
+
+	if (function_invocation_error) {
 		/* No compatible function exists */
 		STAGE3_ERROR(symbol, symbol, "Invalid parameters in function invocation: %s\n", ((identifier_c *)symbol->function_name)->value);
 	} 
-#if 0	
-	else
-	if (NULL == symbol->datatype) {
-		/* One or compatible functions exists, but none chosen! */
-		STAGE3_ERROR(symbol, symbol, "Invalid parameters in function invocation: %s\n", f_name->value);
-	}
-#endif
 
 	return NULL;
 }
@@ -1075,17 +1015,32 @@
  */
 // SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list, symbol_c *called_fb_declaration;)
 void *print_datatypes_error_c::visit(fb_invocation_c *symbol) {
-	list_c *parameter_list;
-
-	if (NULL != symbol->formal_param_list)
-		parameter_list = (list_c *)symbol->formal_param_list;
-	else if (NULL != symbol->nonformal_param_list)
-		parameter_list = (list_c *)symbol->nonformal_param_list;
-	else ERROR;
-
-	parameter_list->accept(*this);
-
-	if (NULL == symbol->called_fb_declaration) {
+	symbol_c *param_value, *param_name;
+	function_call_param_iterator_c fcp_iterator(symbol);
+	bool function_invocation_error = false;
+
+	if ((NULL != symbol->formal_param_list) && (NULL != symbol->nonformal_param_list)) 
+		ERROR;
+
+	if (NULL != symbol->formal_param_list) {
+		symbol->formal_param_list->accept(*this);
+		while ((param_name = fcp_iterator.next_f()) != NULL) {
+			param_value = fcp_iterator.get_current_value();
+			if (NULL == param_value->datatype) {
+				function_invocation_error = true;
+			}
+		}
+	}
+	if (NULL != symbol->nonformal_param_list) {
+		symbol->nonformal_param_list->accept(*this);
+		while ((param_value = fcp_iterator.next_nf()) != NULL) {
+			if (NULL == param_value->datatype) {
+				function_invocation_error = true;
+			}
+		}
+	}
+
+	if (function_invocation_error) {
 		/* Invalid parameters for FB call! */
 		STAGE3_ERROR(symbol, symbol, "Invalid parameters in FB invocation: %s\n", ((identifier_c *)symbol->fb_name)->value);
 	}