# HG changeset patch # User Mario de Sousa # Date 1352471676 0 # Node ID d1987756887875466fea83df2be0e811ff65792c # Parent d475ae61c7f838a104ee2d0b62df467d6a9eebd6 Check for errors in enum datatype declarations. (This is not yet complete as it will not yet stop the compilation process if these errors are found) diff -r d475ae61c7f8 -r d19877568878 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Fri Nov 09 13:08:18 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Fri Nov 09 14:34:36 2012 +0000 @@ -72,6 +72,32 @@ #define VALID_CVALUE(dtype, symbol) (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status) #define IS_OVERFLOW(dtype, symbol) (symbol_c::cs_overflow == (symbol)->const_value._##dtype.status) + + + +#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2)) +#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2)) + + +#define STAGE3_ERROR(error_level, symbol1, symbol2, ...) { \ + fprintf(stderr, "%s:%d-%d..%d-%d: error: ", \ + FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\ + LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ +} + + +#define STAGE3_WARNING(symbol1, symbol2, ...) { \ + fprintf(stderr, "%s:%d-%d..%d-%d: warning: ", \ + FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\ + LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ +} + + + /* set to 1 to see debug info during execution */ static int debug = 0; @@ -86,9 +112,11 @@ /* Add to the global_enumerated_value_symtable the global enum value constants, i.e. the enum constants used in the enumerated * datatypes that are defined inside a TYPE ... END_TYPE declaration. */ - - symbol_c null_globalenumvalue_symbol; /* cannot be static, so it may be used in the template!! */ - static dsymtable_c global_enumerated_value_symtable; +/* NOTE: we do not store any NULL values in this symbol table, so we can safely use NULL and the null value. */ + +symbol_c null_enumvalue_symbol; /* cannot be static, so it may be used in the template!! */ +typedef dsymtable_c enumerated_value_symtable_t; +static enumerated_value_symtable_t global_enumerated_value_symtable; class populate_globalenumvalue_symtable_c: public iterator_visitor_c { @@ -128,16 +156,14 @@ if (current_enumerated_type == NULL) ERROR; if (symbol->type != NULL) ERROR; - symbol_c *value_type = global_enumerated_value_symtable.find_value(symbol->value); - /* NOTE: The following condition checks whether the same identifier is used more than once - * when defining the enumerated values of the type declaration of the new enumerated type. - * If this occurs, then the program beeing compiled contains a semantic error, which - * must be caught and reported by the semantic analyser. However, since - * this code is run before the semantic analyser, we must not yet raise the ERROR (internal - * compiler error message). - * For this reason, the follosing check is commented out. - */ - /* if (value_type == current_enumerated_type) ERROR; */ + enumerated_value_symtable_t::iterator lower = global_enumerated_value_symtable.lower_bound(symbol->value); + enumerated_value_symtable_t::iterator upper = global_enumerated_value_symtable.upper_bound(symbol->value); + for (; lower != upper; lower++) + if (lower->second == current_enumerated_type) { + /* The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */ + STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type."); + return NULL; /* No need to insert it! It is already in the table! */ + } global_enumerated_value_symtable.insert(symbol->value, current_enumerated_type); return NULL; @@ -200,8 +226,7 @@ * END_FUNCTION_BLOCK */ - symbol_c null_localenumvalue_symbol; /* cannot be static, so it may be used in the template!! */ - static dsymtable_c local_enumerated_value_symtable; +static enumerated_value_symtable_t local_enumerated_value_symtable; class populate_enumvalue_symtable_c: public iterator_visitor_c { @@ -241,7 +266,14 @@ /* this is really an ERROR! The initial value may use the syntax NUM_TYPE#enum_value, but in that case we should have return'd in the above statement !! */ if (symbol->type != NULL) ERROR; - symbol_c *local_value_type = local_enumerated_value_symtable.find_value(symbol->value); + enumerated_value_symtable_t::iterator lower = local_enumerated_value_symtable.lower_bound(symbol->value); + enumerated_value_symtable_t::iterator upper = local_enumerated_value_symtable.upper_bound(symbol->value); + for (; lower != upper; lower++) + if (lower->second == current_enumerated_type) { + /* The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */ + STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type."); + return NULL; /* No need to insert it! It is already in the table! */ + } /* add it to the local symbol table. */ local_enumerated_value_symtable.insert(symbol->value, current_enumerated_type); @@ -383,7 +415,6 @@ if(param_name == NULL) return false; } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); - /* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */ /* Get the parameter type */ param_datatype = base_type(fp_iterator.param_type()); @@ -774,8 +805,6 @@ /* B 1.2.3.1 - Duration */ /************************/ void *fill_candidate_datatypes_c::visit(duration_c *symbol) { - /* TODO: check whether the literal follows the rules specified in section '2.2.3.1 Duration' of the standard! */ - add_datatype_to_candidate_list(symbol, symbol->type_name); if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n"; return NULL; @@ -903,8 +932,44 @@ symbol_c *local_enumerated_type; symbol_c *enumerated_type; - if (NULL != symbol->type) - enumerated_type = symbol->type; /* TODO: check whether the value really belongs to that datatype!! */ + if (NULL != symbol->type) { +#if 1 + enumerated_type = symbol->type; +#else + /* NOTE: The following code works but is not complete, that is why it is currently commented out! + * + * It is not complete because it does not yet consider the following situation: + * + * TYPE + * base_enum_t: (x1, x2, x3); + * enum_t1 : base_enum_t := x1; + * enum_t2 : base_enum_t := x2; + * enum_t12: enum_t1 := x2; + * END_TYPE + * + * considering the above, ALL of the following are correct! + * base_enum_t#x1 + * enum_t1#x1 + * enum_t2#x1 + * enum_t12#x1 + * + * However, the following code only considers + * base_enum_t#x1 + * as correct, and all the others as incorrect! + */ + /* check whether the value really belongs to that datatype!! */ + /* All local enum values are declared inside anonymous enumeration datatypes (i.e. inside a VAR ... END_VAR declaration, with + * the enum type having no type name), so thay cannot possibly be referenced using a datatype_t#enumvalue syntax. + * Because of this, we only look for the datatype identifier in the global enum value symbol table! + */ + enumerated_type = NULL; // assume error... + enumerated_value_symtable_t::iterator lower = global_enumerated_value_symtable.lower_bound(symbol->value); + enumerated_value_symtable_t::iterator upper = global_enumerated_value_symtable.upper_bound(symbol->value); + for (; lower != upper; lower++) + if (compare_identifiers(search_base_type_c::get_basetype_id(lower->second), symbol->type) == 0) // returns 0 if identifiers are equal!! + enumerated_type = symbol->type; +#endif + } else { symbol_c *global_enumerated_type = global_enumerated_value_symtable.find_value (symbol->value); symbol_c * local_enumerated_type = local_enumerated_value_symtable.find_value (symbol->value);