# HG changeset patch
# User mjsousa
# Date 1376993740 -3600
# Node ID 783ef40344dd9ad69f9d22dbc4bad8c5e95512b5
# Parent  27f246b35ac2c5f573bd4393dbcd92ca79156412
Add support for FB call semantics of 'S' and 'R' IL operators!
Remove segfaults when analysing buggy IL code (IL operators with no operands).

diff -r 27f246b35ac2 -r 783ef40344dd stage3/fill_candidate_datatypes.cc
--- a/stage3/fill_candidate_datatypes.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -555,17 +555,13 @@
  *        CU counter_var
  */
 void *fill_candidate_datatypes_c::handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration) {
-	symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(il_operand);
-  	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_type_id) ERROR;
-
-	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id);
-	if (function_block_type_symtable.end_value() == fb_decl)
-		/* The il_operand is not the name of a FB instance. Most probably it is the name of a variable of some other type.
-		 * this is a semantic error.
-		 */
-		fb_decl = NULL;
-	
+	symbol_c *fb_decl = (NULL == il_operand)? NULL : search_varfb_instance_type->get_basetype_decl(il_operand);
+	if (! get_datatype_info_c::is_function_block(fb_decl)) fb_decl = NULL;
+
+	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
+	/* However, when calling using the 'S' and 'R' operators, this error is not caught by stage 2, as these operators have two possible semantics */
+	// if (NULL == fb_type_id) ERROR;
+
 	/* The narrow_candidate_datatypes_c does not rely on this called_fb_declaration pointer being == NULL to conclude that
 	 * we have a datatype incompatibility error, so we set it to fb_decl to allow the print_datatype_error_c to print out
 	 * more informative error messages!
@@ -594,10 +590,54 @@
 
 
 
+
+/* handle the S and R IL operators... */
+/* operator_str should be set to either "S" or "R" */
+void *fill_candidate_datatypes_c::handle_S_and_R_operator(symbol_c *symbol, const char *operator_str, symbol_c *&called_fb_declaration) {
+	/* NOTE: this operator has two possible semantic meanings:
+	 *          - Set/Reset the BOOL operand variable to true
+	 *          - call the FB specified by the operand.
+	 *       Which of the two semantics will have to be determined by the datatype of the operand!
+	 */
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
+
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			/* IEC61131-3, Table 52, Note (e) states that the datatype of the operand must be BOOL!
+			 * IEC61131-3, Table 52, line 3 states that this operator should "Set operand to 1 if current result is Boolean 1"
+			 *     which implies that the prev_instruction_type MUST also be BOOL compatible.
+			 */
+			if (get_datatype_info_c::is_BOOL_compatible(prev_instruction_type) && get_datatype_info_c::is_BOOL_compatible(operand_type))
+				add_datatype_to_candidate_list(symbol, prev_instruction_type);
+		}
+	}
+
+	/* if the appropriate semantics is not a Set/Reset of a boolean variable, the we try for the FB invocation! */
+	if (symbol->candidate_datatypes.size() == 0) 
+		handle_implicit_il_fb_call(symbol,  operator_str, called_fb_declaration);
+
+	/* If it is also not a valid FB call, make sure the candidate_datatypes is empty (handle_implicit_il_fb_call may leave it non-empty!!) */
+	/* From here on out, all later code will consider the symbol->called_fb_declaration being NULL as an indication that this operator must use the
+	 * Set/Reset semantics, so we must also guarantee that the remainder of the state of this symbol is compatible with that assumption!
+	 */
+	if (NULL == called_fb_declaration)
+		symbol->candidate_datatypes.clear();
+
+	if (debug) std::cout << operator_str << " [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+
 /* handle a binary IL operator, like ADD, SUB, etc... */
 void *fill_candidate_datatypes_c::handle_binary_operator(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr) {
-	if (NULL == l_expr) /* if no prev_il_instruction */
-		return NULL; 
+	if (NULL == l_expr) return NULL; /* if no prev_il_instruction */
+	if (NULL == r_expr) return NULL; /* if no IL operand!! */
 
 	for(unsigned int i = 0; i < l_expr->candidate_datatypes.size(); i++)
 		for(unsigned int j = 0; j < r_expr->candidate_datatypes.size(); j++)
@@ -1553,21 +1593,11 @@
  * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
  * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
  */
-/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */
+/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 */
 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
 void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
-	/* We do not call
-	 * fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
-	 * because we want to make sure it is a FB instance, and not some other data type...
-	 */
-	symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(symbol->fb_name);
-	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_type_id) ERROR;
-
- 	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id);
-	if (function_block_type_symtable.end_value() == fb_decl) 
-		/* The fb_name not the name of a FB instance. Most probably it is the name of a variable of some other type. */
-		fb_decl = NULL;
+	symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
+	if (! get_datatype_info_c::is_function_block(fb_decl)) fb_decl = NULL;
 
 	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
 	if (NULL == fb_decl) ERROR;
@@ -1664,6 +1694,7 @@
 /* B 2.2 Operators */
 /*******************/
 void *fill_candidate_datatypes_c::visit(LD_operator_c *symbol) {
+	if (NULL == il_operand)          return NULL;
 	for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
 		add_datatype_to_candidate_list(symbol, il_operand->candidate_datatypes[i]);
 	}
@@ -1672,6 +1703,7 @@
 }
 
 void *fill_candidate_datatypes_c::visit(LDN_operator_c *symbol) {
+	if (NULL == il_operand)          return NULL;
 	for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
 		if      (get_datatype_info_c::is_ANY_BIT_compatible(il_operand->candidate_datatypes[i]))
 			add_datatype_to_candidate_list(symbol, il_operand->candidate_datatypes[i]);
@@ -1684,6 +1716,7 @@
 	symbol_c *prev_instruction_type, *operand_type;
 
 	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
 	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
 		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
 			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
@@ -1700,6 +1733,7 @@
 	symbol_c *prev_instruction_type, *operand_type;
 
 	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
 	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
 		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
 			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
@@ -1720,6 +1754,7 @@
 	 *       We do not need to generate an error message. This error will be caught somewhere else!
 	 */
 	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
 	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
 		if (get_datatype_info_c::is_ANY_BIT_compatible(prev_il_instruction->candidate_datatypes[i]))
 			add_datatype_to_candidate_list(symbol, prev_il_instruction->candidate_datatypes[i]);
@@ -1729,58 +1764,17 @@
 }
 
 
-void *fill_candidate_datatypes_c::visit(S_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	symbol_c *prev_instruction_type, *operand_type;
-
-	if (NULL == prev_il_instruction) return NULL;
-	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
-			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
-			operand_type = il_operand->candidate_datatypes[j];
-			/* TODO: I believe the following is wrong! The data types of prev_instruction_type and operand_type DO NOT have to be equal.
-			 * the prev_instruction_type MUST be BOOL compatible.
-			 * I am not too sure about operand_type, does it have to be BOOL compatible, or can it be ANY_BIT compatible? Must check!
-			 */
-			if (get_datatype_info_c::is_type_equal(prev_instruction_type,operand_type) && get_datatype_info_c::is_BOOL_compatible(operand_type))
-				add_datatype_to_candidate_list(symbol, prev_instruction_type);
-		}
-	}
-	if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
-
-
-void *fill_candidate_datatypes_c::visit(R_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	symbol_c *prev_instruction_type, *operand_type;
-
-	if (NULL == prev_il_instruction) return NULL;
-	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
-			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
-			operand_type = il_operand->candidate_datatypes[j];
-			/* TODO: I believe the following is wrong! The data types of prev_instruction_type and operand_type DO NOT have to be equal.
-			 * the prev_instruction_type MUST be BOOL compatible.
-			 * I am not too sure about operand_type, does it have to be BOOL compatible, or can it be ANY_BIT compatible? Must check!
-			 */
-			if (get_datatype_info_c::is_type_equal(prev_instruction_type,operand_type) && get_datatype_info_c::is_BOOL_compatible(operand_type))
-				add_datatype_to_candidate_list(symbol, prev_instruction_type);
-		}
-	}
-	if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
-
-
-void *fill_candidate_datatypes_c::visit( S1_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "S1", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( R1_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "R1", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(   S_operator_c *symbol) {return handle_S_and_R_operator   (symbol,   "S", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(   R_operator_c *symbol) {return handle_S_and_R_operator   (symbol,   "R", symbol->called_fb_declaration);}
+
+void *fill_candidate_datatypes_c::visit(  S1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "S1", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  R1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "R1", symbol->called_fb_declaration);}
 void *fill_candidate_datatypes_c::visit( CLK_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CLK", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( CU_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "CU", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( CD_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "CD", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( PV_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "PV", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( IN_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "IN", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( PT_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "PT", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  CU_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "CU", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  CD_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "CD", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  PV_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "PV", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  IN_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "IN", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  PT_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "PT", symbol->called_fb_declaration);}
 
 void *fill_candidate_datatypes_c::visit( AND_operator_c *symbol) {return handle_binary_operator(widen_AND_table, symbol, prev_il_instruction, il_operand);}
 void *fill_candidate_datatypes_c::visit(  OR_operator_c *symbol) {return handle_binary_operator( widen_OR_table, symbol, prev_il_instruction, il_operand);}
@@ -1969,17 +1963,9 @@
 /* B 3.2.2 Subprogram Control Statements */
 /*****************************************/
 void *fill_candidate_datatypes_c::visit(fb_invocation_c *symbol) {
-	symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(symbol->fb_name);
-	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_type_id) ERROR;
-
-	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id);
-	if (function_block_type_symtable.end_value() == fb_decl) 
-		/* The fb_name not the name of a FB instance. Most probably it is the name of a variable of some other type. */
-		fb_decl = NULL;
-
-	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_decl) ERROR;
+	symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
+	if (! get_datatype_info_c::is_function_block(fb_decl )) fb_decl = NULL;
+	if (NULL == fb_decl) ERROR; /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
 	
 	if (symbol->   formal_param_list != NULL) symbol->formal_param_list->accept(*this);
 	if (symbol->nonformal_param_list != NULL) symbol->nonformal_param_list->accept(*this);
diff -r 27f246b35ac2 -r 783ef40344dd stage3/fill_candidate_datatypes.hh
--- a/stage3/fill_candidate_datatypes.hh	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/fill_candidate_datatypes.hh	Tue Aug 20 11:15:40 2013 +0100
@@ -89,7 +89,8 @@
     bool  match_nonformal_call(symbol_c *f_call, symbol_c *f_decl);
     bool  match_formal_call   (symbol_c *f_call, symbol_c *f_decl, symbol_c **first_param_datatype = NULL);
     void  handle_function_call(symbol_c *fcall, generic_function_call_t fcall_data);
-    void *handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration);
+    void *handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name,   symbol_c *&called_fb_declaration);
+    void *handle_S_and_R_operator   (symbol_c *symbol,         const char *operator_str, symbol_c *&called_fb_declaration);
     void *handle_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_expression  (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_operator    (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
diff -r 27f246b35ac2 -r 783ef40344dd stage3/narrow_candidate_datatypes.cc
--- a/stage3/narrow_candidate_datatypes.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -322,11 +322,9 @@
 
 	/* set the datatype of the il_operand, this is, the FB being called! */
 	if (NULL != il_operand) {
-		/* only set it if it is in the candidate datatypes list! */  
-		set_datatype(called_fb_declaration, il_operand);
+		set_datatype(called_fb_declaration, il_operand); /* only set it if it is in the candidate datatypes list! */  
 		il_operand->accept(*this);
 	}
-	symbol_c *fb_decl = il_operand->datatype;
 
 	if (0 == fake_prev_il_instruction->prev_il_instruction.size()) {
 		/* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction
@@ -336,8 +334,10 @@
 		return NULL;
 	}
 
+	symbol_c *fb_decl = (NULL == il_operand)? NULL : il_operand->datatype;
+	
 	if (NULL == fb_decl) {
-		/* the il_operand is a not FB instance */
+		/* the il_operand is a not FB instance, or it simply does not even exist, */
 		/* so we simply pass on the required datatype to the prev_il_instructions */
 		/* The invalid FB invocation will be caught in the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
 		set_datatype_in_prev_il_instructions(il_instruction->datatype, fake_prev_il_instruction);
@@ -999,7 +999,7 @@
  * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
  * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
  */
-/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */
+/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 */
 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
 void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
 	symbol_c *fb_decl = symbol->called_fb_declaration;
@@ -1093,7 +1093,9 @@
         if (NULL != deprecated_operation)
 		*deprecated_operation = false;
 
-	/* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
+
+	 /* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
 	 * e.g.  LD 33
 	 *       AND ( 45
 	 *            OR 56
@@ -1136,9 +1138,8 @@
 
 
 void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) {
-	if (NULL == symbol->datatype)
-		/* next IL instructions were unable to determine the datatype this instruction should produce */
-		return NULL;
+	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
+  
 	/* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
 	 * e.g.  LD 33
 	 *       AND ( 45
@@ -1158,6 +1159,7 @@
 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	  
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	return NULL;
@@ -1167,10 +1169,10 @@
 
 
 void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol)   {
-	if (NULL == symbol->datatype)
-		/* next IL instructions were unable to determine the datatype this instruction should produce */
-		return NULL;
+	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
+
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	return NULL;
@@ -1178,10 +1180,10 @@
 
 
 void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol)  {
-	if (NULL == symbol->datatype)
-		/* next IL instructions were unable to determine the datatype this instruction should produce */
-		return NULL;
+	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
+
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	return NULL;
@@ -1190,28 +1192,39 @@
 void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) {
 	if (symbol->candidate_datatypes.size() != 1)
 		return NULL;
+
 	symbol->datatype = symbol->candidate_datatypes[0];
-	/* set the datatype for the operand */
-	il_operand->datatype = symbol->datatype;
-	il_operand->accept(*this);
 	/* set the desired datatype of the previous il instruction */
 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
 	 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
 	 */
 	current_il_instruction->datatype = symbol->datatype;
+	
+	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+
 	return NULL;
 }
 
 void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) {
 	if (symbol->candidate_datatypes.size() != 1)
 		return NULL;
+	
 	symbol->datatype = symbol->candidate_datatypes[0];
+	/* set the desired datatype of the previous il instruction */
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
+	/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
+	 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
+	 */
+	current_il_instruction->datatype = symbol->datatype;
+
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
-	/* set the desired datatype of the previous il instruction */
-	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -1220,22 +1233,23 @@
 	 *              NOT [<il_operand>]
 	 *       However, it does not define the semantic of the NOT operation when the <il_operand> is specified.
 	 *       We therefore consider it an error if an il_operand is specified!
-	 */
-	/* We do not change the data type, we simply invert the bits in bit types! */
+	 *       This error will be detected in print_datatypes_error_c!!
+	 */
+	/* This operator does not change the data type, it simply inverts the bits in the ANT_BIT data types! */
 	/* So, we set the desired datatype of the previous il instruction */
 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
 void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol)  {
-  /* TODO: what if this is a FB call? */
-	return handle_il_instruction(symbol);
-}
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return narrow_implicit_il_fb_call(symbol, "S",  symbol->called_fb_declaration); 
+	else                                       /* Reset   semantics */  return handle_il_instruction(symbol);
+}
+
 void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol)  {
-  /* TODO: what if this is a FB call? */
-	return handle_il_instruction(symbol);
-}
-
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return narrow_implicit_il_fb_call(symbol, "R",  symbol->called_fb_declaration); 
+	else                                       /* Reset   semantics */  return handle_il_instruction(symbol);
+}
 
 void *narrow_candidate_datatypes_c::visit(  S1_operator_c *symbol)  {return narrow_implicit_il_fb_call(symbol, "S1",  symbol->called_fb_declaration);}
 void *narrow_candidate_datatypes_c::visit(  R1_operator_c *symbol)  {return narrow_implicit_il_fb_call(symbol, "R1",  symbol->called_fb_declaration);}
diff -r 27f246b35ac2 -r 783ef40344dd stage3/print_datatypes_error.cc
--- a/stage3/print_datatypes_error.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/print_datatypes_error.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -278,7 +278,7 @@
 		STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name);
 		return NULL;
 	}
-	il_operand->accept(*this);
+	// il_operand->accept(*this);  // NOT required. The il_simple_operation_c already visits it!!
 	
 	if (NULL == called_fb_declaration) {
 		STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance.");
@@ -760,10 +760,8 @@
 
 void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) {
 	il_operand = symbol->il_operand;
-	if (NULL != symbol->il_operand) {
-		symbol->il_operand->accept(*this);
-	}
-	/* recursive call to see whether data types are compatible */
+	if (NULL != il_operand)     symbol->il_operand->accept(*this); /* recursive call to see whether data types are compatible */
+
 	symbol->il_simple_operator->accept(*this);
 	il_operand = NULL;
 	return NULL;
@@ -932,50 +930,22 @@
 /* B 2.2 Operators */
 /*******************/
 void *print_datatypes_error_c::print_binary_operator_errors(const char *il_operator, symbol_c *symbol, bool deprecated_operation) {
-	if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) {
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator);
-	} else if (NULL == symbol->datatype) {
-		STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator);
+	if (NULL == il_operand) {
+		STAGE3_ERROR(0, symbol, symbol, "Missing operand for %s operator.", il_operator);		// message (a)
+	} else if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator);		// message (b)
+	} else if (NULL == symbol->datatype) {
+		STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator);		// message (c)
 	} else if (deprecated_operation)
-		STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator);
-	return NULL;
-}
-
-
-void *print_datatypes_error_c::visit(LD_operator_c *symbol) {
-	return NULL;
-}
-
-void *print_datatypes_error_c::visit(LDN_operator_c *symbol) {
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'LDN' operator.");
-	return NULL;
-}
-
-void *print_datatypes_error_c::visit(ST_operator_c *symbol) {
-	/* 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.
-	 * What do you think?
-	 */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'ST' operator.");
-	return NULL;
-}
-
-void *print_datatypes_error_c::visit(STN_operator_c *symbol) {
-	/* 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.
-	 * What do you think?
-	 */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'STN' operator.");
-	return NULL;
-}
+		STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator);		// message (d)
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(  LD_operator_c *symbol) {return print_binary_operator_errors("LD"  , symbol);}  // I believe it will never emit messages (b) and (c)!!
+void *print_datatypes_error_c::visit( LDN_operator_c *symbol) {return print_binary_operator_errors("LDN" , symbol);}  // I believe it will never emit message (c)
+void *print_datatypes_error_c::visit(  ST_operator_c *symbol) {return print_binary_operator_errors("ST"  , symbol);}  // I believe it will never emit message (c)
+void *print_datatypes_error_c::visit( STN_operator_c *symbol) {return print_binary_operator_errors("STN" , symbol);}  // I believe it will never emit message (c)
 
 void *print_datatypes_error_c::visit(NOT_operator_c *symbol) {
 	/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>
@@ -983,27 +953,21 @@
 	 *       However, it does not define the semantic of the NOT operation when the <il_operand> is specified.
 	 *       We therefore consider it an error if an il_operand is specified!
 	 */
-	if (il_operand != NULL)
+	if (il_operand != NULL) {
 		STAGE3_ERROR(0, symbol, symbol, "'NOT' operator may not have an operand.");
-	if (symbol->candidate_datatypes.size() == 0)
+	} else if (symbol->candidate_datatypes.size() == 0)
 		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'NOT' operator.");
 	return NULL;
 }
 
 void *print_datatypes_error_c::visit(S_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'S' operator.");
-	return NULL;
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return handle_implicit_il_fb_invocation("S", symbol, symbol->called_fb_declaration);
+	else                                       /* Reset   semantics */  return print_binary_operator_errors    ("S", symbol);
 }
 
 void *print_datatypes_error_c::visit(R_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'R' operator.");
-	return NULL;
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return handle_implicit_il_fb_invocation("R", symbol, symbol->called_fb_declaration);
+	else                                       /* Reset   semantics */  return print_binary_operator_errors    ("R", symbol);
 }
 
 void *print_datatypes_error_c::visit( S1_operator_c *symbol) {return handle_implicit_il_fb_invocation( "S1", symbol, symbol->called_fb_declaration);}
diff -r 27f246b35ac2 -r 783ef40344dd stage4/generate_c/generate_c_il.cc
--- a/stage4/generate_c/generate_c_il.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage4/generate_c/generate_c_il.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -1530,6 +1530,16 @@
 
 
 void *visit(S_operator_c *symbol) {
+  /* This operator must implement one of two possible semantics: 
+   *     - FB call
+   *     - Set all the bits of an ANY_BIT type variable to 1
+   */
+  
+  /* Check whether we must implement the FB call semantics... */
+  if (NULL != symbol->called_fb_declaration)
+    return XXX_CAL_operator( "S", this->current_operand);
+  
+  /* Implement the bit setting semantics... */
   if (wanted_variablegeneration != expression_vg) {
     s4o.print("LD");
     return NULL;
@@ -1552,6 +1562,16 @@
 
 
 void *visit(R_operator_c *symbol) {
+  /* This operator must implement one of two possible semantics: 
+   *     - FB call
+   *     - Set all the bits of an ANY_BIT type variable to 0
+   */
+  
+  /* Check whether we must implement the FB call semantics... */
+  if (NULL != symbol->called_fb_declaration)
+    return XXX_CAL_operator( "R", this->current_operand);
+  
+  /* Implement the bit setting semantics... */
   if (wanted_variablegeneration != expression_vg) {
     s4o.print("LD");
     return NULL;