diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index b8968e0abda9da86d179dbb4d3447fa7ca6eef09..c39d84f26fbc171fa42cdad9e0e778568f3d248b 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -309,7 +309,7 @@ %type <number> star_cbl_opt close_how %type <number> test_before usage_clause1 might_be -%type <boolean> all optional sign_leading on_off initialized +%type <boolean> all optional sign_leading on_off initialized strong %type <number> count data_clauses data_clause %type <number> nine nps relop spaces_etc reserved_value signed %type <number> rounded rounded_mode rounded_type round_between @@ -326,7 +326,7 @@ %type <refer> rel_operand num_value num_term value factor %type <field_data> value78 -%type <field> literal name nume +%type <field> literal name nume typename %type <field> advance_by num_literal signed_literal %type <refer> perform_times %type <perf> perform_verb perform_inline @@ -808,6 +808,7 @@ statement_begin( const YYLTYPE& loc, int token ) { cbl_enabled_exceptions_array_t enabled(enabled_exceptions); parser_exception_prepare( keyword_str(token), &enabled ); } + if( getenv(__func__) ) symbol_temporaries_free(); } %} @@ -3845,15 +3846,28 @@ sign_separate: %empty { $$ = false; } /* * "The effect of the TYPE clause is as though the data description identified - * by type-name- 1 had been coded in place of the TYPE clause, excluding the + * by type-name-1 had been coded in place of the TYPE clause, excluding the * level-number, name, alignment, and the GLOBAL, SELECT WHEN, and TYPEDEF * clauses specified for type-name-1;" + * + * The essential characteristics of a type, which is identified by its + * type-name, are the: + * — relative positions and lengths of the elementary items + * — ALIGNED clause + * — BLANK WHEN ZERO clause + * — JUSTIFIED clause + * — PICTURE clause + * — SIGN clause + * — SYNCHRONIZED clause + * — USAGE clause */ -type_clause: is TYPE strong +type_clause: TYPE to typename { cbl_field_t *field = current_field(); - field->attr |= typedef_e; - yywarn("warning: TYPEDEF not implemented"); + if( $typename ) { + symbol_field_same_as(field, $typename); + } + yywarn("warning: TYPE TO is provisional"); } ; @@ -3861,7 +3875,8 @@ typedef_clause: is TYPEDEF strong { cbl_field_t *field = current_field(); field->attr |= typedef_e; - yywarn("warning: TYPEDEF not implemented"); + if( $strong ) field->attr |= strongdef_e; + yywarn("warning: TYPEDEF is provisional"); } ; @@ -5316,6 +5331,19 @@ refmod: LPAREN expr[from] ':' expr[len] ')' %prec NAME } ; +typename: qname + { + auto e = symbol_typedef(PROGRAM, names); + if( ! e ) { + yyerrorv("error: symbol '%s' not found", names.back() ); + names.clear(); + YYERROR; + } + $$ = cbl_field_of(e); + names.clear(); + } + ; + name: qname { $$ = NULL; @@ -9387,8 +9415,8 @@ sign: %empty status: %empty | STATUS ; -strong: %empty - | STRONG +strong: %empty { $$ = true; } + | STRONG { $$ = false; } ; times: %empty diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc index 95b3316c69b8cc3b34658c9cc9525598042a4ae7..928ee0961f9cb6fbb9893b07e3069cb929b1fd8b 100644 --- a/gcc/cobol/symbols.cc +++ b/gcc/cobol/symbols.cc @@ -2462,7 +2462,7 @@ symbol_field_add( size_t program, struct cbl_field_t *field ) * TYPEDEF is relevant only in Data Division. */ struct symbol_elem_t * -symbol_typedef( size_t program, size_t parent, const char name[] ) +symbol_typedef_DNU( size_t program, size_t parent, const char name[] ) { class match_field { size_t program, parent; diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index ee87d2908205617fe9c5a129fe806ca4d4668cdd..17ca9f3fc9fc5703bd6a4bb58615849444296f14 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -2091,8 +2091,7 @@ size_t current_program_index(); const char * current_declarative_section_name(); -struct symbol_elem_t * symbol_typedef( size_t program, - size_t parent, const char name[] ); +struct symbol_elem_t * symbol_typedef( size_t program, std::list<const char *> names ); struct symbol_elem_t * symbol_field( size_t program, size_t parent, const char name[] ); struct cbl_label_t * symbol_program( size_t parent, const char name[] ); diff --git a/gcc/cobol/symfind.cc b/gcc/cobol/symfind.cc index 0dd6646601a06c7db9d389b628f879867af73bf3..3100e4054b75de17ec48a559b28b87156f1d99dd 100644 --- a/gcc/cobol/symfind.cc +++ b/gcc/cobol/symfind.cc @@ -386,7 +386,7 @@ size_t end_of_group( size_t igroup ); static std::vector<size_t> symbol_match2( size_t program, std::list<const char *> names, - bool local = true ) + bool local = true, bool want_type = false ) { std::vector<size_t> fields; @@ -397,19 +397,23 @@ symbol_match2( size_t program, if( e->program != program ) break; if( e->type != SymField ) continue; - if( is_typedef(e) ) { + bool right_kind = ( want_type && is_typedef(e)) || + (!want_type && !is_typedef(e)); +#if 0 + if( !right_kind ) { auto isym = end_of_group( symbol_index(e) ); e = symbol_at(--isym); continue; } - - if( name_has_names( e, names, local ) ) { +#endif + + if( right_kind && name_has_names( e, names, local ) ) { fields.push_back( symbol_index(e) ); } } if( fields.empty() ){ - if( program > 0 ) { // try containing program + if( program > 0 && !want_type ) { // try containing program program = cbl_label_of(symbol_at(program))->parent; return symbol_match2( program, names, program == 0 ); } @@ -448,7 +452,7 @@ symbol_match2( size_t program, * The names list is in top-down order, front-to-back. This function * iterates backwards over the list, looking for the parent of N at * N-1. -*/ + */ static symbol_map_t symbol_match( size_t program, std::list<const char *> names ) { auto matched = symbol_match2( program, names ); @@ -469,6 +473,17 @@ symbol_match( size_t program, std::list<const char *> names ) { return output; } +struct symbol_elem_t * +symbol_typedef( size_t program, std::list<const char *> names ) { + auto types = symbol_match2(program, names, true, true); + if( types.empty() ) return NULL; + if( types.size() > 1 ) { + yyerrorv("error: %s is not a unique TYPEDEF name", names.back()); + return NULL; + } + return symbol_at( types.front() ); +} + std::pair <symbol_elem_t *, bool> symbol_find( size_t program, std::list<const char *> names ) { symbol_map_t items = symbol_match(program, names);