diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index a1cdbc3c091fe3ae21d6d1c71a5d19b66e18a6bf..be0f86d8d7f071c89c599c5b09c166820ca482b1 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -4317,6 +4317,7 @@ declaratives: %empty parser_label_label($label); enabled_exceptions = current.enabled_exception_cache; current.enabled_exception_cache.clear(); + ast_enter_section(implicit_section()); } ; @@ -4337,7 +4338,7 @@ sentences: sentence { apply_declaratives(); } | sentences sentence - { // sentences might not be sentence + { // sentences might not be sentence ast_first_statement(@2.first_line); symbol_temporaries_free(); } diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index 29604f3dfa433b295dccc591faf6385a4ba1ee40..08468df3ac173db79156133c6396d8e4f1482b1f 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -2068,6 +2068,20 @@ static class current_t { return programs.empty()? NULL : programs.top().paragraph; } + bool is_first_statement( int line ) { + if( ! in_declaratives && first_statement == 0 ) { + if( ! symbol_label_section_exists(program_index()) ) { + if( ! dialect_ibm() ) { + yyerror("error: ISO programs with DECLARATIVES must begin with a SECTION " + "unless -dialect ibm"); + } + } + first_statement = line; + return true; + } + return false; + } + /* * At the end of each program, ensure there are no uses of an ambiguous * procedure (SECTION or PARAGRAPH) name. At the end of a top-level program, @@ -2139,14 +2153,6 @@ static class current_t { return symbol_index(symbol_elem_of(section)); } - bool is_first_statement( int line ) { - if( ! in_declaratives && first_statement == 0 ) { - first_statement = line; - return true; - } - return false; - } - cbl_label_t *doing_declaratives( bool begin ) { if( begin ) { in_declaratives = true; diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc index f8c99455834a8c7ef3cb70f4f5c1e0204b2f31fa..b111c60710d5b62ad1b6e2ae73b04daedd35693b 100644 --- a/gcc/cobol/symbols.cc +++ b/gcc/cobol/symbols.cc @@ -3993,6 +3993,45 @@ symbol_label_add( size_t program, cbl_label_t *input ) return cbl_label_of(e); } +/* + * Under ISO (and not IBM) Declaratives are followed by a Section name. When + * the first statement is parsed, the last symbol in the table is the first + * symbol, if any, in the Procedure Division. If it's a user-defined Section + * name, it doesn't matter if there are Declaratives. Else check to see if + * there *are* Declaratives to notify the user of the missing Section name. + */ +bool +symbol_label_section_exists( size_t program ) { + auto pblob = std::find_if( symbols_begin(program), symbols_end(), + []( const auto& sym ) { + if( sym.type == SymField ) { + auto& f( sym.elem.field ); + return f.type == FldBlob; + } + return false; + } ); + if( pblob == symbols_end() ) return true; // Section name not required + + bool has_section = std::any_of( ++pblob, symbols_end(), + []( const auto& sym ) { + if( sym.type == SymLabel ) { + auto& L(sym.elem.label); + if( L.type == LblSection ) { + if( L.name[0] != '_' ) { // not implicit + return true; // Section name exists + } + } + } + return false; + } ); + if( yydebug && ! has_section ) { + symbols_dump(program, true); + } + // Return true if no Declaratives, because the (non-)requirement is met. + // Return false if Declaratives exist, because no Section name was found. + return has_section; +} + cbl_label_t * symbol_program_add( size_t program, cbl_label_t *input ) { diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index e6c06498b2fa40ab57a1afb7f25da5681b1c0fd9..300ea335830d20afd4419bf37ccddf8c63c3427a 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -2386,6 +2386,8 @@ struct symbol_elem_t * symbol_file_add( size_t program, struct symbol_elem_t * symbol_section_add( size_t program, struct cbl_section_t *section ); +bool symbol_label_section_exists( size_t program ); + size_t symbol_field_capacity( const cbl_field_t *field ); void symbol_cobol_filename_begin( const char filename[] );