From ed4464c5094817e762713a3e41f1af3fa6bb37bc Mon Sep 17 00:00:00 2001 From: "James K. Lowden" <jklowden@symas.com> Date: Tue, 16 Apr 2024 18:30:16 -0400 Subject: [PATCH] reuse of temporaries causes crashes, see sentences nonterminal --- gcc/cobol/parse.y | 2 +- gcc/cobol/parse_ante.h | 2 +- gcc/cobol/symbols.cc | 117 ++++++++++++++++++++--------------------- gcc/cobol/symbols.h | 8 ++- 4 files changed, 61 insertions(+), 68 deletions(-) diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 4729bf7cc276..c08baf627c84 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -4040,7 +4040,7 @@ sentences: sentence { symbol_temporaries_free(); } | sentences sentence { - if( $1 != PARAGRAPH ) + if( false && $2 != PARAGRAPH ) symbol_temporaries_free(); } ; diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index 8d2c8a4a7a82..e48035f788fc 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -365,7 +365,7 @@ struct evaluate_elem_t { typedef list<case_t>::iterator case_iter; case_iter pcase; - void dump() const { +void dump() const { warnx( "nother=%zu label '%s', %zu cases", nother, label.name, cases.size() ); std::for_each( cases.begin(), cases.end(), case_t::Dump ); } diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc index 84aa35a264a4..36e8aa3a0652 100644 --- a/gcc/cobol/symbols.cc +++ b/gcc/cobol/symbols.cc @@ -2983,7 +2983,7 @@ static cbl_field_t * new_temporary_impl( enum cbl_field_type_t type ) { extern int yylineno; - static int temp_num = 1; + static int nstack, nliteral; static const struct cbl_field_t empty_alpha = { 0, FldAlphanumeric, FldInvalid, temporary_e | intermediate_e, 0, 0, 0, nonarray, 0, "", @@ -3027,8 +3027,16 @@ new_temporary_impl( enum cbl_field_type_t type ) } f->line = yylineno; - snprintf(f->name, sizeof(f->name), "_stack%d",temp_num++); - + if( is_literal(type) ) { + snprintf(f->name, sizeof(f->name), "_literal%d",++nliteral); + } else { + snprintf(f->name, sizeof(f->name), "_stack%d",++nstack); + + if( getenv("symbol_temporaries_free") ) { + warnx("%s: %s, %s", __func__, f->name, 3 + cbl_field_type_str(f->type)); + } + } + return f; } @@ -3045,12 +3053,6 @@ parser_symbol_add2( cbl_field_t *field ) { return field; } -static cbl_field_t * -new_temporary_add( enum cbl_field_type_t type ) { - cbl_field_t *field = new_temporary_impl(type); - return parser_symbol_add2(field); -} - static cbl_field_t * new_literal_add( const char initial[], uint32_t len, enum cbl_field_attr_t attr ) { static char empty[2] = "\0"; @@ -3110,6 +3112,45 @@ new_literal( uint32_t len, const char initial[], enum cbl_field_attr_t attr ) { return temporaries.literal(initial, len, attr); } +void +temporaries_t::dump() const { + char *output; + extern int yylineno; + + asprintf(&output, "%4d: %zu Literals", yylineno, literals.size()); + for( const auto& elem : used ) { + if( ! elem.second.empty() ) { + char *so_far = output; + asprintf(&output, "%s, %zu %s", + so_far, + elem.second.size(), + 3 + cbl_field_type_str(elem.first)); + free(so_far); + } + } + warnx("status: %s", output); + free(output); +} + +temporaries_t::~temporaries_t() { + if( getenv( "symbol_temporaries_free" ) ) { + warnx("%s: %zu literals", __func__, literals.size()); + for( const auto& elem : literals ) { + const literal_an& key(elem.first); + fprintf(stderr, "%c '%s'\n", key.is_quoted? 'Q' : ' ', key.value.c_str()); + } + dump(); + } +} + +cbl_field_t * +temporaries_t::add( cbl_field_t *field ) { + auto p = used[field->type].insert(field); + bool yn(p.second); + assert(yn); + return *p.first; +}; + cbl_field_t * temporaries_t::reuse( cbl_field_type_t type ) { auto& fields = freed[type]; @@ -3123,52 +3164,23 @@ temporaries_t::reuse( cbl_field_type_t type ) { fields.erase(p); } - used[type].insert(field); - return field; + return add(field); } cbl_field_t * temporaries_t::acquire( cbl_field_type_t type ) { cbl_field_t *field = reuse(type); - if( field ) { - parser_symbol_add(field); // notify of reuse - } else { - field = new_temporary_add(type); - } - return field; -} - -size_t -temporaries_t::keep() { - keepers.push(used); - used.clear(); - return keepers.size(); -} - -void -temporaries_t::release( size_t keeper ) { - if( keepers.size() != keeper ) { - warnx("%s: logic error: releasing %zu of %zu kept temporaries:", - __func__, keeper, keepers.size() ); - } - assert( ! keepers.empty() ); - assert( keepers.size() == keeper ); - fieldmap_t& used( keepers.top() ); - - for( auto& elem : used ) { - const cbl_field_type_t& type(elem.first); - temporaries_t::fieldset_t& used(elem.second); - - auto freer = std::inserter(freed[type], - freed[type].begin()); - std::copy( used.begin(), used.end(), freer ); + if( !field ) { + field = new_temporary_impl(type); + add(field); } - keepers.pop(); + return parser_symbol_add2(field); // notify of reuse } void symbol_temporaries_free() { + if( getenv(__func__) ) temporaries.dump(); for( auto& elem : temporaries.used ) { const cbl_field_type_t& type(elem.first); temporaries_t::fieldset_t& used(elem.second); @@ -3180,23 +3192,6 @@ symbol_temporaries_free() { } } -size_t -symbol_temporaries_push() { - return temporaries.keep(); -} - -void -symbol_temporaries_pop( size_t kept ) { - return temporaries.release( kept ); -} - -void -temporaries_t::add( cbl_field_t *field ) { - auto p = used[field->type].insert(field); - bool yn(p.second); - assert(yn); -}; - cbl_field_t * new_alphanumeric( size_t capacity ) { cbl_field_t * field = new_temporary_impl(FldAlphanumeric); diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index 1181b0b3baae..14cbbb2431dc 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -1246,13 +1246,11 @@ public: cbl_field_t * literal( const char value[], uint32_t len, cbl_field_attr_t attr = none_e ); cbl_field_t * reuse( cbl_field_type_t type ); cbl_field_t * acquire( cbl_field_type_t type ); - size_t keep(); - void release( size_t kept); - void add( cbl_field_t *field ); + cbl_field_t * add( cbl_field_t *field ); + void dump() const; + ~temporaries_t(); }; -size_t symbol_temporaries_push(); -void symbol_temporaries_pop( size_t kept ); static inline bool is_table( const cbl_field_t *field ) { return field && field->occurs.ntimes() > 0; -- GitLab