Add a new pou_typename_c object to the AST to store references to previously declared Functions, FB, and Programs.
authormjsousa
Sat, 06 Dec 2014 19:11:32 +0000
changeset 958 7474d2cd1d6e
parent 957 4489afa5b1c5
child 959 8bfcc8e62bd6
Add a new pou_typename_c object to the AST to store references to previously declared Functions, FB, and Programs.
absyntax/absyntax.cc
absyntax/absyntax.def
absyntax/absyntax.hh
absyntax_utils/function_call_iterator.cc
absyntax_utils/function_call_iterator.hh
absyntax_utils/get_datatype_info.cc
absyntax_utils/search_base_type.cc
absyntax_utils/search_base_type.hh
absyntax_utils/spec_init_separator.cc
absyntax_utils/spec_init_separator.hh
absyntax_utils/type_initial_value.cc
absyntax_utils/type_initial_value.hh
stage1_2/create_enumtype_conversion_functions.cc
stage1_2/create_enumtype_conversion_functions.hh
stage1_2/iec_bison.yy
stage3/fill_candidate_datatypes.cc
stage3/print_datatypes_error.cc
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_base.cc
stage4/generate_c/generate_c_typedecl.cc
stage4/generate_c/generate_c_vardecl.cc
stage4/generate_c/generate_var_list.cc
stage4/generate_iec/generate_iec.cc
--- a/absyntax/absyntax.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax/absyntax.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -172,7 +172,16 @@
   /* corrent the new size */
   n--;
   /* elements = (symbol_c **)realloc(elements, n * sizeof(symbol_c *)); */
-}
+  /* TODO: adjust the location parameters, taking into account the removed element. */
+}
+
+
+/* remove element at position pos. */
+void list_c::clear(void) {
+  n = 0;
+  /* TODO: adjust the location parameters, taking into account the removed element. */
+}
+
 
 #define SYM_LIST(class_name_c, ...)								\
 class_name_c::class_name_c(									\
--- a/absyntax/absyntax.def	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax/absyntax.def	Sat Dec 06 19:11:32 2014 +0000
@@ -128,6 +128,7 @@
 /* A special identifier class, used for identifiers that have been previously declared as a derived datatype */
 /*  This is currently needed because generate_c stage 4 needs to handle the array datatype identifiers differently to all other identifiers. */
 SYM_TOKEN(derived_datatype_identifier_c) 
+SYM_TOKEN(poutype_identifier_c) 
 
 
 /*********************/
--- a/absyntax/absyntax.hh	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax/absyntax.hh	Sat Dec 06 19:11:32 2014 +0000
@@ -247,6 +247,8 @@
     virtual void insert_element(symbol_c *elem, int pos = 0);
      /* remove element at position pos. */
     virtual void remove_element(int pos = 0);
+     /* remove all elements from list. Does not delete the elements in the list! */ 
+    virtual void clear(void);
 };
 
 
--- a/absyntax_utils/function_call_iterator.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/function_call_iterator.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -89,10 +89,10 @@
 }
 
 /* Returns the name of the currently referenced function invocation */
-identifier_c *function_call_iterator_c::fname(void) {
-  identifier_c *identifier = dynamic_cast<identifier_c *>(current_fcall_name);
-  if (identifier == NULL) ERROR;
-  return identifier;
+token_c *function_call_iterator_c::fname(void) {
+  token_c *fname_sym = dynamic_cast<token_c *>(current_fcall_name);
+  if (fname_sym == NULL) ERROR;
+  return fname_sym;
 }
 
 
--- a/absyntax_utils/function_call_iterator.hh	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/function_call_iterator.hh	Sat Dec 06 19:11:32 2014 +0000
@@ -73,7 +73,7 @@
     symbol_c *next(void);
 
     /* Returns the name of the currently referenced function invocation */
-    identifier_c *fname(void);
+    token_c *fname(void);
 
   private:
   /***************************************/
--- a/absyntax_utils/get_datatype_info.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/get_datatype_info.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -149,12 +149,18 @@
      *       That anotation is specific to the generate_c stage4 code, and must therefore NOT be referenced
      *       in the absyntax_utils code, as this last code should be independent of the stage4 version!
      */ 
-    
+
     /*****************************/
     /* B 1.5.2 - Function Blocks */
     /*****************************/
     /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
     void *visit(function_block_declaration_c  *symbol)  {return symbol->fblock_name;}
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
+    void *visit(program_declaration_c  *symbol)  {return symbol->program_type_name;}
+    
 }; // get_datatype_id_c 
 
 get_datatype_id_c *get_datatype_id_c::singleton = NULL;
@@ -200,7 +206,12 @@
     /* B 1.1 - Letters, digits and identifiers */
     /*******************************************/
     void *visit(                 identifier_c *symbol) {return (void *)symbol->value;};
-    void *visit(derived_datatype_identifier_c *symbol) {return (void *)symbol->value;};
+    // Should not be necessary, as datatype declarations currently use an identifier_c for their name! 
+    // Only references to the datatype (when declaring variable, for ex., will use poutype_identifier_c
+    void *visit(derived_datatype_identifier_c *symbol) {return (void *)symbol->value;};   
+    // Should not be necessary, as FB declarations currently use an identifier_c for their name! 
+    // Only references to the FB (when declaring variable, for ex., will use poutype_identifier_c
+    void *visit(         poutype_identifier_c *symbol) {return (void *)symbol->value;};  
 
     /***********************************/
     /* B 1.3.1 - Elementary Data Types */
@@ -277,11 +288,23 @@
      *       in the absyntax_utils code, as this last code should be independent of the stage4 version!
      */ 
     
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    /* Functions are not really datatypes, but we include it here as it helps in printing out error messages!   */
+    /* Currently this is needed only by remove_forward_depencies_c::print_circ_error()                          */
+    /*  FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
+    void *visit(      function_declaration_c  *symbol)  {return symbol->derived_function_name->accept(*this);}
     /*****************************/
     /* B 1.5.2 - Function Blocks */
     /*****************************/
     /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
     void *visit(function_block_declaration_c  *symbol)  {return symbol->fblock_name->accept(*this);}    
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
+    void *visit(       program_declaration_c  *symbol)  {return symbol->program_type_name->accept(*this);} 
 };
 
 get_datatype_id_str_c *get_datatype_id_str_c::singleton = NULL;
--- a/absyntax_utils/search_base_type.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/search_base_type.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -131,8 +131,9 @@
   return NULL;
 }
 
-void *search_base_type_c::visit(                 identifier_c *type_name) {return handle_datatype_identifier(type_name);}  // still needed to handle FB and program datatypes!
-void *search_base_type_c::visit(derived_datatype_identifier_c *type_name) {return handle_datatype_identifier(type_name);}
+void *search_base_type_c::visit(                 identifier_c *type_name) {return handle_datatype_identifier(type_name);}  
+void *search_base_type_c::visit(derived_datatype_identifier_c *type_name) {return handle_datatype_identifier(type_name);}  
+void *search_base_type_c::visit(         poutype_identifier_c *type_name) {return handle_datatype_identifier(type_name);}  
 
 
 /*********************/
--- a/absyntax_utils/search_base_type.hh	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/search_base_type.hh	Sat Dec 06 19:11:32 2014 +0000
@@ -91,7 +91,8 @@
   /*******************************************/
     void *visit(                 identifier_c *type_name);
     void *visit(derived_datatype_identifier_c *type_name);
-    
+    void *visit(         poutype_identifier_c *type_name);
+
   /*********************/
   /* B 1.2 - Constants */
   /*********************/
--- a/absyntax_utils/spec_init_separator.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/spec_init_separator.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -74,11 +74,12 @@
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
 // SYM_TOKEN(identifier_c)
-/* visitor for identifier_c is necessary because spec_init_sperator_c will be called to analyse PROGRAM identfiers,
- * which are still transformed into identfier_c, instead of a derived_datatype_identifier_c
- */
-void *spec_init_sperator_c::visit(                 identifier_c *symbol) {
-  TRACE("spec_init_sperator_c::identifier_c");
+/* visitor for identifier_c should no longer be necessary. All references to derived datatypes are now stored in then */
+/* AST using either poutype_identifier_c or derived_datatype_identifier_c                                             */
+void *spec_init_sperator_c::visit(                 identifier_c *symbol) { ERROR; return NULL;} /* should never occur */
+
+void *spec_init_sperator_c::visit(         poutype_identifier_c *symbol) {
+  TRACE("spec_init_sperator_c::poutype_identifier_c");
   switch (search_what) {
     /* if we ever get called sith a simple identifier_c, then it must be a previously declared type... */
     case search_spec: return symbol;
@@ -90,7 +91,7 @@
   
   
 void *spec_init_sperator_c::visit(derived_datatype_identifier_c *symbol) {
-  TRACE("spec_init_sperator_c::identifier_c");
+  TRACE("spec_init_sperator_c::derived_datatype_identifier_c");
   switch (search_what) {
     /* if we ever get called sith a simple identifier_c, then it must be a previously declared type... */
     case search_spec: return symbol;
@@ -226,6 +227,7 @@
   }
   ERROR; /* should never occur */
   return NULL;
+
 }
 
 
--- a/absyntax_utils/spec_init_separator.hh	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/spec_init_separator.hh	Sat Dec 06 19:11:32 2014 +0000
@@ -67,7 +67,8 @@
   // SYM_TOKEN(identifier_c)
   void *visit(                 identifier_c *symbol);
   void *visit(derived_datatype_identifier_c *symbol);
-  
+  void *visit(         poutype_identifier_c *symbol);
+
 
   /********************************/
   /* B 1.3.3 - Derived data types */
--- a/absyntax_utils/type_initial_value.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/type_initial_value.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -110,48 +110,29 @@
 void *type_initial_value_c::handle_type_spec(symbol_c *base_type_name, symbol_c *type_spec_init) {
   if (type_spec_init != NULL)
      return type_spec_init;
-   /* no initial value specified, so we return
-   * the initial value of the type this type is based on...
-    */
+  /* no initial value specified, so we return the initial value of the type this type is based on... */
   return base_type_name->accept(*this);
 }
 
 
-/* visitor for identifier_c is necessary because type_initial_value_c will be called to analyse PROGRAM identfiers,
- * which are still transformed into identfier_c, instead of a derived_datatype_identifier_c
- */
-void *type_initial_value_c::visit(                 identifier_c *type_name) {
+void *type_initial_value_c::handle_type_name(symbol_c *type_name) {
   /* look up the type declaration... */
   symbol_c *type_decl = type_symtable.find_value(type_name);
-  if (type_decl == type_symtable.end_value())
     /* Type declaration not found!! */
-    /* NOTE: Variables declared out of function block 'data types',
-     *    for eg:  VAR  timer: TON; END_VAR
-     * do not have a default value, so (TON) will never be found in the
-     * type symbol table. This means we cannot simply consider this
-     * an error and abort, but must rather return a NULL.
+    /* NOTE: Variables declared out of function block 'data types',for eg:  VAR  timer: TON; END_VAR
+     * do not have a default value, so (TON) will never be found in the type symbol table. This means 
+     * we cannot simply consider this an error and abort, but must rather return a NULL.
      */
-     return NULL;
+  if (type_decl == type_symtable.end_value())   return NULL;
 
   return type_decl->accept(*this);
 }
 
-  
-void *type_initial_value_c::visit(derived_datatype_identifier_c *type_name) {
-  /* look up the type declaration... */
-  symbol_c *type_decl = type_symtable.find_value(type_name);
-  if (type_decl == type_symtable.end_value())
-    /* Type declaration not found!! */
-    /* NOTE: Variables declared out of function block 'data types',
-     *    for eg:  VAR  timer: TON; END_VAR
-     * do not have a default value, so (TON) will never be found in the
-     * type symbol table. This means we cannot simply consider this
-     * an error and abort, but must rather return a NULL.
-     */
-     return NULL;
-
-  return type_decl->accept(*this);
-}
+/* visitor for identifier_c should no longer be necessary. All references to derived datatypes are now stored in then          */
+/* AST using either poutype_identifier_c or derived_datatype_identifier_c. In principe, the following should not be necesasry  */
+void *type_initial_value_c::visit(                 identifier_c *symbol) {return handle_type_name(symbol);} /* should never occur */
+void *type_initial_value_c::visit(         poutype_identifier_c *symbol) {return handle_type_name(symbol);} /* in practice it might never get called, as FB, Functions and Programs do not have initial value  */
+void *type_initial_value_c::visit(derived_datatype_identifier_c *symbol) {return handle_type_name(symbol);}
 
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
--- a/absyntax_utils/type_initial_value.hh	Sun Nov 30 12:49:42 2014 +0000
+++ b/absyntax_utils/type_initial_value.hh	Sat Dec 06 19:11:32 2014 +0000
@@ -84,10 +84,12 @@
     static type_initial_value_c *_instance;
     static type_initial_value_c *instance(void);
     void *handle_type_spec(symbol_c *base_type_name, symbol_c *type_spec_init);
+    void *handle_type_name(symbol_c *type_name);
 
   private:
-    void *visit(                 identifier_c *type_name);
-    void *visit(derived_datatype_identifier_c *type_name);
+    void *visit(                 identifier_c *symbol);
+    void *visit(derived_datatype_identifier_c *symbol);
+    void *visit(         poutype_identifier_c *symbol);
 
     /***********************************/
     /* B 1.3.1 - Elementary Data Types */
--- a/stage1_2/create_enumtype_conversion_functions.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage1_2/create_enumtype_conversion_functions.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -76,11 +76,12 @@
     return singleton->text;
 }
 
-
-void *create_enumtype_conversion_functions_c::visit(identifier_c *symbol) {
-    currentToken = symbol->value;
-    return NULL;
-}
+/* As the name of derived datatypes and POUs are still stored as identifiers in the respective datatype and POU declaration,  */
+/* only the indintifier_c visitor should be necessary!                                                                        */
+void *create_enumtype_conversion_functions_c::visit(                 identifier_c *symbol) {currentToken = symbol->value; return NULL;}
+void *create_enumtype_conversion_functions_c::visit(         poutype_identifier_c *symbol) {ERROR; return NULL;}
+void *create_enumtype_conversion_functions_c::visit(derived_datatype_identifier_c *symbol) {ERROR; return NULL;}
+
 
 /**********************/
 /* B 1.3 - Data types */
--- a/stage1_2/create_enumtype_conversion_functions.hh	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage1_2/create_enumtype_conversion_functions.hh	Sat Dec 06 19:11:32 2014 +0000
@@ -55,7 +55,10 @@
     virtual ~create_enumtype_conversion_functions_c(void);
     static std::string &get_declaration(symbol_c *symbol);
 
-    void *visit(identifier_c *symbol);
+    void *visit(                 identifier_c *symbol);
+    void *visit(         poutype_identifier_c *symbol);
+    void *visit(derived_datatype_identifier_c *symbol);
+    
     /**********************/
     /* B 1.3 - Data types */
     /**********************/
--- a/stage1_2/iec_bison.yy	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage1_2/iec_bison.yy	Sat Dec 06 19:11:32 2014 +0000
@@ -224,7 +224,10 @@
 /* The functions declared here are defined at the end of this file... */
 
 /* Convert an il_operator_c into an identifier_c */
-symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator);
+identifier_c         *il_operator_c_2_identifier_c        (symbol_c *il_operator);
+/* Convert an il_operator_c into an poutype_identifier_c */
+poutype_identifier_c *il_operator_c_2_poutype_identifier_c(symbol_c *il_operator);
+
 
 /* return if current token is a syntax element */
 /* ERROR_CHECK_BEGIN */
@@ -1597,16 +1600,25 @@
 | prev_declared_array_type_name             {$$ = new identifier_c(((token_c *)$1)->value, locloc(@$));}; // change the derived_datatype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
 | prev_declared_structure_type_name         {$$ = new identifier_c(((token_c *)$1)->value, locloc(@$));}; // change the derived_datatype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
 | prev_declared_string_type_name            {$$ = new identifier_c(((token_c *)$1)->value, locloc(@$));}; // change the derived_datatype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
-| prev_declared_derived_function_name
-| prev_declared_derived_function_block_name
-| prev_declared_program_type_name
+| prev_declared_derived_function_name       {$$ = new identifier_c(((token_c *)$1)->value, locloc(@$));}; // change the          poutype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
+| prev_declared_derived_function_block_name {$$ = new identifier_c(((token_c *)$1)->value, locloc(@$));}; // change the          poutype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
+| prev_declared_program_type_name           {$$ = new identifier_c(((token_c *)$1)->value, locloc(@$));}; // change the          poutype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
 /**/
 | prev_declared_resource_name
 | prev_declared_program_name
 | prev_declared_global_var_name
 ;
 
-
+/* NOTE: Notice that the symbol classes:
+ *            - derived_datatype_identifier_c
+ *            - poutype_identifier_c
+ *       are only inserted into the AST when referencing a derived dataype or a POU
+ *       (e.g. when declaring a variable, making a function call, instantiating a program in a resource,
+ *        or delaring a derived datatype that derives from another previously delcared datatype).
+ *
+ *       In the declaration of the datatype or POU itself, the name of the datatype or POU will be stored
+ *       inside an identifier_c instead!!
+ */
 prev_declared_variable_name:        prev_declared_variable_name_token        {$$ = new identifier_c($1, locloc(@$));};
 prev_declared_fb_name:              prev_declared_fb_name_token              {$$ = new identifier_c($1, locloc(@$));};
 
@@ -1618,9 +1630,11 @@
 prev_declared_string_type_name:     prev_declared_string_type_name_token     {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
 prev_declared_ref_type_name:        prev_declared_ref_type_name_token        {$$ = new derived_datatype_identifier_c($1, locloc(@$));};  /* defined in IEC 61131-3 v3 */
 
-prev_declared_derived_function_name:       prev_declared_derived_function_name_token       {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_program_type_name:           prev_declared_program_type_name_token           {$$ = new identifier_c($1, locloc(@$));};
+prev_declared_derived_function_name:       prev_declared_derived_function_name_token       {$$ = new poutype_identifier_c($1, locloc(@$));};
+prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new poutype_identifier_c($1, locloc(@$));};
+prev_declared_program_type_name:           prev_declared_program_type_name_token           {$$ = new poutype_identifier_c($1, locloc(@$));};
+/* NOTE: The poutype_identifier_c was introduced to allow the implementation of remove_forward_dependencies_c */
+
 
 
 
@@ -4825,9 +4839,10 @@
 //| standard_function_name_simpleop_only_clashes
 ;
 
+/* standard_function_name_no_clashes is only used in function invocations, so we use the poutype_identifier_c class! */
 standard_function_name_no_clashes:
   standard_function_name_token
-	{$$ = new identifier_c($1, locloc(@$));}
+	{$$ = new poutype_identifier_c($1, locloc(@$));}
 ;
 
 
@@ -4836,9 +4851,10 @@
 //| standard_function_name_simpleop_only_clashes
 ;
 
+/* standard_function_name_NOT_clashes is only used in function invocations, so we use the poutype_identifier_c class! */
 standard_function_name_NOT_clashes:
   NOT
-	{$$ = new identifier_c(strdup("NOT"), locloc(@$));}
+	{$$ = new poutype_identifier_c(strdup("NOT"), locloc(@$));}
 ;
 
 /* Add here any other IL simple operators that collide
@@ -4853,39 +4869,40 @@
 ;
 */
 
+/* standard_function_name_expression_clashes is only used in function invocations, so we use the poutype_identifier_c class! */
 standard_function_name_expression_clashes:
-  AND	{$$ = new identifier_c(strdup("AND"), locloc(@$));}
-| OR	{$$ = new identifier_c(strdup("OR"), locloc(@$));}
-| XOR	{$$ = new identifier_c(strdup("XOR"), locloc(@$));}
-| ADD	{$$ = new identifier_c(strdup("ADD"), locloc(@$));}
-| SUB	{$$ = new identifier_c(strdup("SUB"), locloc(@$));}
-| MUL	{$$ = new identifier_c(strdup("MUL"), locloc(@$));}
-| DIV	{$$ = new identifier_c(strdup("DIV"), locloc(@$));}
-| MOD	{$$ = new identifier_c(strdup("MOD"), locloc(@$));}
-| GT	{$$ = new identifier_c(strdup("GT"), locloc(@$));}
-| GE	{$$ = new identifier_c(strdup("GE"), locloc(@$));}
-| EQ	{$$ = new identifier_c(strdup("EQ"), locloc(@$));}
-| LT	{$$ = new identifier_c(strdup("LT"), locloc(@$));}
-| LE	{$$ = new identifier_c(strdup("LE"), locloc(@$));}
-| NE	{$$ = new identifier_c(strdup("NE"), locloc(@$));}
+  AND	{$$ = new poutype_identifier_c(strdup("AND"), locloc(@$));}
+| OR	{$$ = new poutype_identifier_c(strdup("OR"), locloc(@$));}
+| XOR	{$$ = new poutype_identifier_c(strdup("XOR"), locloc(@$));}
+| ADD	{$$ = new poutype_identifier_c(strdup("ADD"), locloc(@$));}
+| SUB	{$$ = new poutype_identifier_c(strdup("SUB"), locloc(@$));}
+| MUL	{$$ = new poutype_identifier_c(strdup("MUL"), locloc(@$));}
+| DIV	{$$ = new poutype_identifier_c(strdup("DIV"), locloc(@$));}
+| MOD	{$$ = new poutype_identifier_c(strdup("MOD"), locloc(@$));}
+| GT	{$$ = new poutype_identifier_c(strdup("GT"), locloc(@$));}
+| GE	{$$ = new poutype_identifier_c(strdup("GE"), locloc(@$));}
+| EQ	{$$ = new poutype_identifier_c(strdup("EQ"), locloc(@$));}
+| LT	{$$ = new poutype_identifier_c(strdup("LT"), locloc(@$));}
+| LE	{$$ = new poutype_identifier_c(strdup("LE"), locloc(@$));}
+| NE	{$$ = new poutype_identifier_c(strdup("NE"), locloc(@$));}
 /*
-  AND_operator	{$$ = il_operator_c_2_identifier_c($1);}
+  AND_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
 //NOTE: AND2 (corresponding to the source code string '&') does not clash
 //      with a standard function name, so should be commented out!
-//| AND2_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| OR_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| XOR_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| ADD_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| SUB_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| MUL_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| DIV_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| MOD_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| GT_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| GE_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| EQ_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| LT_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| LE_operator	{$$ = il_operator_c_2_identifier_c($1);}
-| NE_operator	{$$ = il_operator_c_2_identifier_c($1);}
+//| AND2_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| OR_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| XOR_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| ADD_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| SUB_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| MUL_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| DIV_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| MOD_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| GT_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| GE_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| EQ_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| LT_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| LE_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
+| NE_operator	{$$ = il_operator_c_2_poutype_identifier_c($1);}
 */
 ;
 
@@ -4893,7 +4910,7 @@
 derived_function_name:
   identifier  /* will never occur during normal parsing, only needed for preparsing to change it to a prev_declared_derived_function_name! */
 | prev_declared_derived_function_name
-	{$$ = $1;
+	{$$ = new identifier_c(((token_c *)$1)->value, locloc(@$)); // transform the poutype_identifier_c into an identifier_c
 	 if (get_preparse_state() && !allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;}
 	}
 | AND
@@ -4927,7 +4944,7 @@
 	 if (get_preparse_state())    {library_element_symtable.insert($2, prev_declared_derived_function_name_token);}
 	 else                         {print_err_msg(locl(@1), locf(@3), "FUNCTION with no variable declarations and no body."); yynerrs++;}
 	 }
-/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */
+/* POST_PARSING and STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */
 | function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION
 	{$$ = new function_declaration_c($1, $3, $4, $5, locloc(@$));
 	 add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */
@@ -6692,7 +6709,7 @@
  *       those whose names coincide with operators !!
  */
 | function_name_no_clashes
-	{$$ = new il_function_call_c($1, NULL, locloc(@$));}
+	{$$ = new il_function_call_c($1, NULL, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 /* NOTE: the line
  *         | il_simple_operator il_operand
  *       already contains the 'NOT', 'MOD', etc. operators, followed by a single il_operand.
@@ -6720,9 +6737,9 @@
  *       are followed by a il_operand_list with __two__ or more il_operands!!
  */
 | function_name_no_clashes il_operand_list
-	{$$ = new il_function_call_c($1, $2, locloc(@$));}
+	{$$ = new il_function_call_c($1, $2, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 | il_simple_operator_clash il_operand_list2
-	{$$ = new il_function_call_c(il_operator_c_2_identifier_c($1), $2, locloc(@$));}
+	{$$ = new il_function_call_c(il_operator_c_2_poutype_identifier_c($1), $2, locloc(@$));}
 ;
 
 
@@ -6881,9 +6898,9 @@
  *       (AND MOD OR XOR ADD DIV EQ GT GE LT LE MUL NE SUB)
  */
   function_name_no_clashes '(' eol_list ')'
-	{$$ = new il_formal_funct_call_c($1, NULL, locloc(@$));}
+	{$$ = new il_formal_funct_call_c($1, NULL, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 | function_name_simpleop_clashes '(' eol_list ')'
-	{$$ = new il_formal_funct_call_c($1, NULL, locloc(@$));}
+	{$$ = new il_formal_funct_call_c($1, NULL, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 /* | function_name '(' eol_list il_param_list ')' */
 /* For the above syntax, we no longer have two ways of interpreting the
  * same syntax. The above is always a function call!
@@ -6898,9 +6915,9 @@
  * We must therefore interpret the IL operators as function names!
  */
 | function_name_no_clashes '(' eol_list il_param_list ')'
-	{$$ = new il_formal_funct_call_c($1, $4, locloc(@$));}
+	{$$ = new il_formal_funct_call_c($1, $4, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 | function_name_simpleop_clashes '(' eol_list il_param_list ')'
-	{$$ = new il_formal_funct_call_c($1, $4, locloc(@$));}
+	{$$ = new il_formal_funct_call_c($1, $4, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 /* The following line should read:
  *
  * | function_name_expression_clashes '(' eol_list il_param_list ')'
@@ -6920,10 +6937,10 @@
  * We need to figure out which symbol was created, destroy it,
  * and create the correct symbol for our case.
  * This is a lot of work, so I put it in a function
- * at the end of this file... il_operator_c_2_identifier_c()
+ * at the end of this file... il_operator_c_2_poutype_identifier_c()
  */
 | il_expr_operator_clash_eol_list il_param_list ')'
-	{$$ = new il_formal_funct_call_c(il_operator_c_2_identifier_c($1), $2, locloc(@$));}
+	{$$ = new il_formal_funct_call_c(il_operator_c_2_poutype_identifier_c($1), $2, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | function_name_no_clashes '(' eol_list error ')'
   {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid parameter list defined in IL formal function call."); yyerrok;} 
@@ -7738,9 +7755,9 @@
 function_invocation:
 /*  function_name '(' [param_assignment_list] ')' */
   function_name_no_NOT_clashes '(' param_assignment_formal_list ')'
-	{$$ = new function_invocation_c($1, $3, NULL, locloc(@$));}
+	{$$ = new function_invocation_c($1, $3, NULL, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 | function_name_no_NOT_clashes '(' param_assignment_nonformal_list ')'
-	{$$ = new function_invocation_c($1, NULL, $3, locloc(@$));}
+	{$$ = new function_invocation_c($1, NULL, $3, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c
 /* ERROR_CHECK_BEGIN */ 
 | function_name_no_NOT_clashes param_assignment_formal_list ')'
   {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function name in ST expression."); yynerrs++;}
@@ -8494,7 +8511,17 @@
 /* NOTE: this code is very ugly and un-eficient, but I (Mario) have many
  *       more things to worry about right now, so just let it be...
  */
-symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator) {
+poutype_identifier_c *il_operator_c_2_poutype_identifier_c(symbol_c *il_operator) {
+  identifier_c         *    id = il_operator_c_2_identifier_c(il_operator);
+  poutype_identifier_c *pou_id = new poutype_identifier_c(strdup(id->value));
+
+  *(symbol_c *)pou_id = *(symbol_c *)id;
+  delete id;
+  return pou_id;
+}
+  
+
+identifier_c *il_operator_c_2_identifier_c(symbol_c *il_operator) {
   const char *name = NULL;
   identifier_c *res;
 
@@ -8560,7 +8587,7 @@
 
   if (name == NULL)
     ERROR;
-
+/*
   res = new identifier_c(strdup(name), 
                          il_operator->first_line,
                          il_operator->first_column,
@@ -8572,6 +8599,11 @@
                          il_operator->last_order
                         );
   free(il_operator);
+*/
+  res = new identifier_c(strdup(name));
+  *(symbol_c *)res = *(symbol_c *)il_operator;
+  delete il_operator;
+  
   return res;
 }
 
--- a/stage3/fill_candidate_datatypes.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -987,7 +987,7 @@
 
 /* enumerated_specification ASSIGN enumerated_value */
 // SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value)
-// NOTE: enumerated_specification is either an enumerated_value_list_c or identifier_c.
+// NOTE: enumerated_specification is either an enumerated_value_list_c or derived_datatype_identifier_c.
 void *fill_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->enumerated_specification, symbol->enumerated_value);}
 
 
--- a/stage3/print_datatypes_error.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage3/print_datatypes_error.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -164,14 +164,14 @@
 				/* Check if there are duplicate parameter values */
 				if(fcp_iterator.search_f(param_name) != param_value) {
 					function_invocation_error = true;
-					STAGE3_ERROR(0, param_name, param_name, "Duplicate parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value);
+					STAGE3_ERROR(0, param_name, param_name, "Duplicate parameter '%s' when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value);
 					continue; /* jump to next parameter */
 				}
 
 				/* Find the corresponding parameter in function declaration */
 				if (NULL == fp_iterator.search(param_name)) {
 					function_invocation_error = true;
-					STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value);
+					STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value);
 					continue; /* jump to next parameter */
 				} 
 
@@ -184,20 +184,20 @@
 					if ((function_param_iterator_c::direction_in    != param_dir) &&
 					    (function_param_iterator_c::direction_inout != param_dir)) {
 						function_invocation_error = true;
-						STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax ':=' used for parameter '%s', when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value);
+						STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax ':=' used for parameter '%s', when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value);
 						continue; /* jump to next parameter */
 					}
 				} else if   (function_call_param_iterator_c::assign_out == call_param_dir) {
 					if ((function_param_iterator_c::direction_out   != param_dir)) {
 						function_invocation_error = true;
-						STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax '=>' used for parameter '%s', when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value);
+						STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax '=>' used for parameter '%s', when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value);
 						continue; /* jump to next parameter */
 					}
 				} else ERROR;
 
 				if (!get_datatype_info_c::is_type_valid(param_value->datatype)) {
 					function_invocation_error = true;
-					STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value);
+					STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value);
 					continue; /* jump to next parameter */
 				}
 			}
@@ -223,7 +223,7 @@
 					 * We will iterate through all the real previous IL instructions, and analyse each of them one by one */
 					if (il_instruction_symbol->prev_il_instruction.size() == 0) {
 						function_invocation_error = true;
-						STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((identifier_c *)fcall_data.function_name)->value);
+						STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((token_c *)fcall_data.function_name)->value);
 					}
 #if 0
 					/* NOTE: We currently comment out this code...
@@ -237,14 +237,14 @@
 						symbol_c *value = il_instruction_symbol->prev_il_instruction[p];  
 						if (!get_datatype_info_c::is_type_valid(value->datatype)) {
 							function_invocation_error = true;
-							STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((identifier_c *)fcall_data.function_name)->value);
-							STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value);
+							STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((token_c *)fcall_data.function_name)->value);
+							STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((token_c *)fcall_data.function_name)->value);
 						}
 					}
 #else
 					if (!get_datatype_info_c::is_type_valid(il_instruction_symbol->datatype)) {
 						function_invocation_error = true;
-						STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value);
+						STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((token_c *)fcall_data.function_name)->value);
 					}
 #endif
 					if (function_invocation_error)
@@ -253,7 +253,7 @@
 				} else {
 					if (!get_datatype_info_c::is_type_valid(param_value->datatype)) {
 						function_invocation_error = true;
-						STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value);
+						STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((token_c *)fcall_data.function_name)->value);
 					}
 					param_value->accept(*this);
 				}
@@ -262,12 +262,12 @@
 
 	if (NULL == fcall_data.called_function_declaration) {
 		function_invocation_error = true;
-		STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((identifier_c *)fcall_data.function_name)->value);
+		STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((token_c *)fcall_data.function_name)->value);
 	}
 
 	if (function_invocation_error) {
 		/* No compatible function exists */
-		STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((identifier_c *)fcall_data.function_name)->value);
+		STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((token_c *)fcall_data.function_name)->value);
 	} 
 
 	return;
--- a/stage4/generate_c/generate_c.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage4/generate_c/generate_c.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -1614,13 +1614,10 @@
     /*******************************************/
     /* B 1.1 - Letters, digits and identifiers */
     /*******************************************/
-    
     void *visit(identifier_c *symbol) {
-        if (configuration_name)
-          s4o.print(symbol->value);
-        else
-          generate_c_base_c::visit(symbol);
-        return NULL;
+      if (configuration_name)  s4o.print(symbol->value);
+      else                     generate_c_base_c::visit(symbol);
+      return NULL;
     }
 
     /********************/
@@ -1821,8 +1818,11 @@
           print_retain();
           s4o.print(");\n");
           break;
-        case run_dt:
-          current_program_name = ((identifier_c*)(symbol->program_name))->value;
+        case run_dt: 
+          { identifier_c *tmp_id = dynamic_cast<identifier_c*>(symbol->program_name);
+            if (NULL == tmp_id) ERROR;
+            current_program_name = tmp_id->value;
+	  }
           if (symbol->task_name != NULL) {
             s4o.print(s4o.indent_spaces);
             s4o.print("if (");
@@ -2144,10 +2144,11 @@
 /*******************************************/
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
-    void *visit(identifier_c *symbol) {
-        current_name = symbol->value;
-        return NULL;
-    }
+    void *visit(identifier_c *symbol) {current_name = symbol->value; return NULL;}
+    /* In the derived datatype and POUs declarations, the names are stored as identfier_c, so the following visitors are not required! */
+    void *visit(derived_datatype_identifier_c *symbol) {ERROR; return NULL;}
+    void *visit(         poutype_identifier_c *symbol) {ERROR; return NULL;}
+    
 
 /********************************/
 /* B 1.3.3 - Derived data types */
@@ -2167,6 +2168,9 @@
 /**************************************/
 /* B.1.5 - Program organization units */
 /**************************************/
+/* WARNING: The following code is buggy when generating an independent pair of files for each POU, as the
+ *          specially created stage4out_c (s4o_c and s4o_h) will not comply with the enable/disable_code_generation_pragma_c
+ */
 #define handle_pou(fname,pname) \
       if (!allow_output) return NULL;\
       if (generate_pou_filepairs__) {\
--- a/stage4/generate_c/generate_c_base.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage4/generate_c/generate_c_base.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -327,7 +327,8 @@
 /*******************************************/
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
-    void *visit(identifier_c *symbol) {return print_token(symbol);}
+    void *visit(                 identifier_c *symbol) {return print_token(symbol);}
+    void *visit(         poutype_identifier_c *symbol) {return print_token(symbol);}
     /* If you need the derived_datatype_identifier_c visitor, then you should probably be 
      * inheriting from generate_c_base_and_typeid_c and not generate_c_base_c !!
      */
@@ -951,7 +952,7 @@
   if (1  < implicit_id_count) ERROR;
   if (1 == implicit_id_count)
     return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-  return symbol->ref_spec->accept(*this); // this is probably pointing to an identifier_c !!
+  return symbol->ref_spec->accept(*this); // this is probably pointing to an ***_identifier_c !!
 }
 
 /* ref_type_decl: identifier ':' ref_spec_init */
--- a/stage4/generate_c/generate_c_typedecl.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage4/generate_c/generate_c_typedecl.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -539,7 +539,7 @@
 void *visit(array_type_declaration_c *symbol) {
   TRACE("array_type_declaration_c");
   
-  // NOTE: remeber that symbol->array_spec_init may point to an identifier_c, which is why we use symbol->array_spec_init->datatype instead!
+  // NOTE: remeber that symbol->array_spec_init may point to a derived_datatype_identifier_c, which is why we use symbol->array_spec_init->datatype instead!
   if (NULL == symbol->array_spec_init->datatype) ERROR;
   identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol->array_spec_init->datatype);
   
@@ -871,9 +871,12 @@
    *       we will keep track of the datatypes that have already been declared, and henceforth
    *       only declare the datatypes that have not been previously defined.
    */
-  if (datatypes_already_defined.find(((identifier_c *)(symbol->ref_type_name))->value) != datatypes_already_defined.end())
+  identifier_c *tmp_id;
+  tmp_id = dynamic_cast<identifier_c *>(symbol->ref_type_name);
+  if (NULL == tmp_id) ERROR;
+  if (datatypes_already_defined.find(tmp_id->value) != datatypes_already_defined.end())
     return NULL; // already defined. No need to define it again!!
-  datatypes_already_defined[((identifier_c *)(symbol->ref_type_name))->value] = 1; // insert this datatype into the list of already defined arrays!
+  datatypes_already_defined[tmp_id->value] = 1; // insert this datatype into the list of already defined arrays!
   
   current_type_name = NULL;
   current_typedefinition = none_td;
--- a/stage4/generate_c/generate_c_vardecl.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage4/generate_c/generate_c_vardecl.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -59,7 +59,7 @@
 };
 
 
-// Does this class really need to derive from generate_c_typedecl_c ???
+
 class generate_c_array_initialization_c: public generate_c_base_and_typeid_c {
 
   public:
@@ -194,7 +194,6 @@
     
     /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
     void *visit(array_specification_c *symbol) {
-      identifier_c* type_name;
       switch (current_mode) {
         case arraysize_am:
           symbol->array_subrange_list->accept(*this);
--- a/stage4/generate_c/generate_var_list.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage4/generate_c/generate_var_list.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -90,7 +90,10 @@
 /***********************************************************************/
 /***********************************************************************/
 
-
+/* TODO: Delete this helper class search_type_symbol_c, as well as the search_fb_typedecl_c
+ *       in the absyntac_utils directory. They are no longer usefull, now that we have
+ *       datatype analysis working!
+ */
 class search_type_symbol_c: public iterator_visitor_c {
 
   public:
@@ -143,7 +146,23 @@
       return (this->current_var_type_name);
     }
 
-    void *visit(identifier_c* symbol) {
+    void *visit(derived_datatype_identifier_c* symbol) {
+      if (this->current_var_type_name == NULL) {
+        this->current_var_type_name = symbol;
+
+        this->current_var_type_symbol = search_fb_typedecl->get_decl(this->current_var_type_name);
+        if (this->current_var_type_symbol != NULL)
+          this->current_var_type_category = function_block_vtc;
+
+        else {
+          this->current_var_type_symbol = search_base_type_c::get_basetype_decl(this->current_var_type_name);
+          this->current_var_type_symbol->accept(*this);
+        }
+      }
+      return NULL;
+    }
+
+    void *visit(poutype_identifier_c* symbol) {
       if (this->current_var_type_name == NULL) {
         this->current_var_type_name = symbol;
 
--- a/stage4/generate_iec/generate_iec.cc	Sun Nov 30 12:49:42 2014 +0000
+++ b/stage4/generate_iec/generate_iec.cc	Sat Dec 06 19:11:32 2014 +0000
@@ -255,6 +255,7 @@
 /*******************************************/
 void *visit(                 identifier_c *symbol) {return print_token(symbol);}
 void *visit(derived_datatype_identifier_c *symbol) {return print_token(symbol);}
+void *visit(         poutype_identifier_c *symbol) {return print_token(symbol);}
 
 /*********************/
 /* B 1.2 - Constants */