diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index ded53436448dbd6ab020b80a9d4d0b6a5bbdca58..4729bf7cc27697dbe0319aebb5d24d5ed4215036 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -3919,6 +3919,14 @@ typedef_clause: is TYPEDEF strong } field->attr |= typedef_e; if( $strong ) field->attr |= strongdef_e; + if( ! current.typedef_add(field) ) { + auto prior = current.has_typedef(field); + assert(prior); + yyerrorv("error: %02d %s IS TYPEDEF is not unique " + "(see %s, line %d)", + field->level, field->name, + prior->name, prior->line); + } } ; diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index 560c479b95a51add171f1d503d2f7ccda9f3335d..8d2c8a4a7a8267a3f6acefd280e907a392d6cd04 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -1366,6 +1366,27 @@ struct error_labels_t { } }; +struct cbl_typedef_less { + bool operator()( const cbl_field_t *a, const cbl_field_t *b ) const { + auto result = strcasecmp(a->name, b->name); + if( result < 0 ) return true; + if( result > 0 ) return false; + + // Names that match are different if they're in different programs + // and neither is external. + auto lhs = field_index(a); + auto rhs = field_index(b); + if( lhs != rhs ) { + if( !a->has_attr(external_e) && !b->has_attr(external_e) ) { + return lhs < rhs; + } + } + return false; + } +}; + +typedef std::set< const cbl_field_t*, cbl_typedef_less > unique_typedefs_t; + static void implicit_paragraph(); static void implicit_section(); @@ -1400,6 +1421,7 @@ class program_stack_t : public std::stack<prog_descr_t> { static class current_t { program_stack_t programs; + unique_typedefs_t typedefs; std::set<function_descr_t> udfs; bool in_declaratives; const char *author, *paragraph; @@ -1489,6 +1511,16 @@ static class current_t { if( yydebug) enabled_exceptions.dump(); } + bool typedef_add( const cbl_field_t *field ) { + auto result = typedefs.insert(field); + return result.second; + } + const cbl_field_t * has_typedef( const cbl_field_t *field ) { + auto found = typedefs.find(field); + return found == typedefs.end()? NULL : *found; + return found == typedefs.end()? NULL : *found; + } + void udf_add( size_t isym ) { auto udf = function_descr_t::init(isym); auto p = udfs.insert(udf);