From 1d0ff3020c45072cabcf7e9d20df0f4c304ba491 Mon Sep 17 00:00:00 2001 From: "James K. Lowden" <jklowden@symas.com> Date: Fri, 17 Jan 2025 18:53:40 -0500 Subject: [PATCH] WIP: bring location to CDF --- gcc/cobol/UAT/testsuite.src/syn_misc.at | 13 +- gcc/cobol/cbldiag.h | 15 +- gcc/cobol/cdf.y | 301 +++++++++++------------- gcc/cobol/cdfval.h | 2 + gcc/cobol/lexio.h | 4 +- gcc/cobol/scan_ante.h | 4 + gcc/cobol/scan_post.h | 2 +- gcc/cobol/symbols.h | 11 +- gcc/cobol/util.cc | 61 ++++- 9 files changed, 222 insertions(+), 191 deletions(-) diff --git a/gcc/cobol/UAT/testsuite.src/syn_misc.at b/gcc/cobol/UAT/testsuite.src/syn_misc.at index 88a317f23c69..33c12c93e4ac 100644 --- a/gcc/cobol/UAT/testsuite.src/syn_misc.at +++ b/gcc/cobol/UAT/testsuite.src/syn_misc.at @@ -826,13 +826,14 @@ AT_DATA([prog.cob], [ CONTINUE . ]) -AT_CHECK([$COMPILE_ONLY -D X prog.cob], [1], [], [prog.cob:4:32: warning: CDF syntax error: no such variable 'BANANA' - 4 | PROCEDURE DIVISION. - | ^ +AT_CHECK([$COMPILE_ONLY -D X prog.cob], [1], [], [prog.cob:5:14: error: CDF syntax error: no such variable 'BANANA' + 5 | >> IF BANANA + | ^ No BANANA here. -prog.cob:4:32: warning: name already in dictionary: X -prog.cob:4:32: warning: X previously defined in :1 -prog.cob:4:32: error: >>CDF parser failed +prog.cob:9:20: error: name already in dictionary: X + 9 | >> DEFINE X 1 + | ^ +prog.cob:9:20: error: X previously defined in :1 prog.cob:10:1: error: syntax error, unexpected invalid token 10 | >> END-IF | ^ diff --git a/gcc/cobol/cbldiag.h b/gcc/cobol/cbldiag.h index 2a4234a5e25e..47892177c6cc 100644 --- a/gcc/cobol/cbldiag.h +++ b/gcc/cobol/cbldiag.h @@ -41,10 +41,12 @@ bool yywarn( const char fmt[], ... ); struct YYLTYPE; #endif #ifndef YDFLTYPE -struct YDFLTYPE; +struct YDFLTYPE; #endif + // an error at a location, called from the parser for semantic errors -void error_msg( const YYLTYPE& loc, const char gmsgid[], ... ); +template <typename LOC> +void error_msg( const LOC& loc, const char gmsgid[], ... ); // for CDF and other warnings that refer back to an earlier line // (not in diagnostic framework yet) @@ -52,7 +54,7 @@ void yyerrorvl( int line, const char *filename, const char fmt[], ... ); void cbl_unimplementedw(const char *gmsgid, ...); // warning void cbl_unimplemented(const char *gmsgid, ...); // error -void cbl_unimplemented_at( const YYLTYPE& loc, const char *gmsgid, ... ); +void cbl_unimplemented_at( const YYLTYPE& loc, const char *gmsgid, ... ); /* * dbgmsg and dbgerr produce messages not intended for the user. They cannot @@ -63,3 +65,10 @@ void cbl_unimplemented_at( const YYLTYPE& loc, const char *gmsgid, ... ); void dbgerr( const char fmt[], ... ); void dbgmsg( const char fmt[], ... ); +template <typename LOC> +void gcc_location_set( const LOC& loc ); + +template <typename LOC> +void location_dump( const char func[], int line, + const char tag[], const LOC& loc); + diff --git a/gcc/cobol/cdf.y b/gcc/cobol/cdf.y index cd96e963f70a..799b7ecda80e 100644 --- a/gcc/cobol/cdf.y +++ b/gcc/cobol/cdf.y @@ -65,6 +65,33 @@ extern char *yytext; static int ydflex(void); #define PROGRAM current_program_index() + +const YYLTYPE& cobol_location(); +static YYLTYPE location_set( const YYLTYPE& loc ); + + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + location_dump("parse.c", N, \ + "rhs N ", YYRHSLOC (Rhs, N)); \ + } \ + else \ + { \ + (Current).first_line = \ + (Current).last_line = YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = \ + (Current).last_column = YYRHSLOC (Rhs, 0).last_column; \ + } \ + location_dump("parse.c", __LINE__, "current", (Current)); \ + gcc_location_set( location_set(Current) ); \ + } while (0) + %} %code requires { @@ -100,8 +127,6 @@ static int ydflex(void); } #pragma GCC diagnostic pop - void yyerror( const char fmt[], ... ); - bool operator==( const cdfval_base_t& lhs, int rhs ); bool operator||( const cdfval_base_t& lhs, const cdfval_base_t& rhs ); bool operator&&( const cdfval_base_t& lhs, const cdfval_base_t& rhs ); @@ -148,18 +173,6 @@ static class exception_turns_t { auto elem = exceptions.find(type); if( elem != exceptions.end() ) return false; // cannot add twice - std::set<size_t> uniq; - - for( auto file : files ) { - auto inserted = uniq.insert(file); - if( ! inserted.second ) { - auto prev = cbl_file_of(symbol_at(*inserted.first)); - yyerror("%s:%d: %s No file-name shall be specified more than once " - "for one exception condition", __func__, __LINE__, prev->name); - return false; - } - } - exceptions[type] = files; return true; } @@ -209,7 +222,7 @@ apply_cdf_turn( exception_turns_t& turns ) { } if( getenv("SHOW_PARSE") ) enabled_exceptions.dump(); return true; -} +} %} %union { @@ -219,7 +232,7 @@ apply_cdf_turn( exception_turns_t& turns ) { cdf_arg_t cdfarg; cdfval_base_t cdfval; cbl_file_t *file; - std::set<cbl_file_t*> *files; + std::set<size_t> *files; } %printer { fprintf(yyo, "'%s'", $$ ); } <string> @@ -284,6 +297,7 @@ apply_cdf_turn( exception_turns_t& turns ) { %define api.token.prefix{YDF_} %locations +%define parse.error verbose %% top: partials { YYACCEPT; } | copy '.' @@ -295,7 +309,7 @@ top: partials { YYACCEPT; } YYACCEPT; } | copy error { - yyerror("COPY directive must end in a '.'"); + error_msg(@error, "COPY directive must end in a '.'"); YYACCEPT; } | completes { YYACCEPT; } @@ -355,14 +369,14 @@ partial: cdf_if /* text */ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override { if( keyword_tok($NAME) ) { - yyerror("%s is a COBOL keyword", $NAME); + error_msg(@NAME, "%s is a COBOL keyword", $NAME); YYERROR; } if( !cdfval_add( $NAME, cdfval_t($value), $override) ) { - yyerror("name already in dictionary: %s", $NAME); + error_msg(@NAME, "name already in dictionary: %s", $NAME); const cdfval_t& entry = dictionary[$NAME]; assert(entry.filename); - yyerror("%s previously defined in %s:%d", + error_msg(@NAME, "%s previously defined in %s:%d", $NAME, entry.filename, entry.lineno); YYERROR; } @@ -370,7 +384,7 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override | CDF_DEFINE cdf_constant NAME '=' cdf_expr[value] override { /* accept, but as error */ if( scanner_parsing() ) { - yyerror("CDF syntax error: %s = value invalid", $NAME); + error_msg(@NAME, "CDF syntax error: %s = value invalid", $NAME); } } | CDF_DEFINE cdf_constant NAME as OFF @@ -394,13 +408,13 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override | CDF_DEFINE FEATURE as ON { auto feature = cbl_gcobol_feature_t($2); if( ! cobol_gcobol_feature_set(feature, true) ) { - yyerror(">>DEFINE %EBCDIC-MODE is invalid within program body"); + error_msg(@FEATURE, ">>DEFINE %EBCDIC-MODE is invalid within program body"); } } | CDF_DEFINE FEATURE as OFF { auto feature = cbl_gcobol_feature_t($2); if( ! cobol_gcobol_feature_set(feature, false) ) { - yyerror(">>DEFINE %EBCDIC-MODE is invalid within program body"); + error_msg(@FEATURE, ">>DEFINE %EBCDIC-MODE is invalid within program body"); } } ; @@ -438,10 +452,8 @@ except_name: EXCEPTION_NAME[ec] { | EXCEPTION_NAME[ec] filenames { assert($ec != ec_none_e); std::list<size_t> files; - std::transform( $filenames->begin(), $filenames->end(), - std::back_inserter(files), - []( const cbl_file_t* f ) { - return symbol_index(symbol_elem_of(f)); } ); + std::copy( $filenames->begin(), $filenames->end(), + std::back_inserter(files) ); exception_turns.add_exception(ec_type_t($ec), files); } ; @@ -454,14 +466,24 @@ except_check: CHECKING on { exception_turns.enabled = true; } } ; -filenames: filename { $$ = new std::set<cbl_file_t*>; $$->insert($1); } - | filenames filename { $1->insert($2); } +filenames: filename { + $$ = new std::set<size_t>; + $$->insert(symbol_index(symbol_elem_of($1))); + } + | filenames filename { + $$ = $1; + auto inserted = $$->insert(symbol_index(symbol_elem_of($2))); + if( ! inserted.second ) { + error_msg(@2, "%s: No file-name shall be specified more than " + " once for one exception condition", $filename->name); + } + } ; filename: NAME { struct symbol_elem_t *e = symbol_file(PROGRAM, $1); if( !(e && e->type == SymFile) ) { - yyerror("invalid file name '%s'", $NAME); + error_msg(@NAME, "invalid file name '%s'", $NAME); YYERROR; } $$ = cbl_file_of(e); @@ -504,7 +526,7 @@ cdf_cond_expr: BOOL $1, $$? "true" : "false"); } } - | cdf_bool_expr { $$ = $1 == 0? false : true; } + | cdf_bool_expr { $$ = $1(@1) == 0? false : true; } | FEATURE DEFINED { const auto& feature($1); $$ = (feature == int(feature & cbl_gcobol_features)); @@ -516,11 +538,11 @@ cdf_cond_expr: BOOL * "Abbreviated combined relation conditions * shall not be specified." */ -cdf_bool_expr: cdf_bool_expr OR cdf_and { $$ = cdfval_t($1 || $3); } +cdf_bool_expr: cdf_bool_expr OR cdf_and { $$ = cdfval_t($1(@1) || $3(@3)); } | cdf_and - ; + ; -cdf_and: cdf_and AND cdf_reloper { $$ = cdfval_t($1 && $3); } +cdf_and: cdf_and AND cdf_reloper { $$ = cdfval_t($1(@1) && $3(@3)); } | cdf_reloper ; @@ -528,22 +550,47 @@ cdf_reloper: cdf_relexpr | NOT cdf_relexpr { $$ = cdfval_t($2.number? 1 : 0); } ; -cdf_relexpr: cdf_relexpr '<' cdf_expr { $$ = $1 < $3; } - | cdf_relexpr LE cdf_expr { $$ = $1 <= $3; } - | cdf_relexpr '=' cdf_expr { $$ = $1 == $3; } - | cdf_relexpr NE cdf_expr { $$ = $1 != $3; } - | cdf_relexpr GE cdf_expr { $$ = $1 >= $3; } - | cdf_relexpr '>' cdf_expr { $$ = $1 > $3; } +cdf_relexpr: cdf_relexpr '<' cdf_expr { $$ = $1(@1) < $3(@3); } + | cdf_relexpr LE cdf_expr { $$ = $1(@1) <= $3(@3); } + | cdf_relexpr '=' cdf_expr { + $$ = cdfval_t(false); + if( ( $1.string && $3.string) || + (!$1.string && !$3.string) ) + { + $$ = $1 == $3; + } else { + const char *msg = $1.string? + "incommensurate comparison is FALSE: '%s' = %ld" : + "incommensurate comparison is FALSE: %ld = '%s'" ; + error_msg(@1, msg); + } + } + | cdf_relexpr NE cdf_expr + { + $$ = cdfval_t(false); + if( ( $1.string && $3.string) || + (!$1.string && !$3.string) ) + { + $$ = $1 != $3; + } else { + const char *msg = $1.string? + "incommensurate comparison is FALSE: '%s' = %ld" : + "incommensurate comparison is FALSE: %ld = '%s'" ; + error_msg(@1, msg); + } + } + | cdf_relexpr GE cdf_expr { $$ = $1(@1) >= $3(@3); } + | cdf_relexpr '>' cdf_expr { $$ = $1(@1) > $3(@3); } | cdf_expr ; -cdf_expr: cdf_expr '+' cdf_expr { $$ = $1 + $3; } - | cdf_expr '-' cdf_expr { $$ = $1 - $3; } - | cdf_expr '*' cdf_expr { $$ = $1 * $3; } - | cdf_expr '/' cdf_expr { $$ = $1 / $3; } - | '+' cdf_expr %prec NEG { $$ = $2; } - | '-'cdf_expr %prec NEG { $$ = negate($2); } - | '(' cdf_bool_expr ')' { $$ = $2; } +cdf_expr: cdf_expr '+' cdf_expr { $$ = $1(@1) + $3(@3); } + | cdf_expr '-' cdf_expr { $$ = $1(@1) - $3(@3); } + | cdf_expr '*' cdf_expr { $$ = $1(@1) * $3(@3); } + | cdf_expr '/' cdf_expr { $$ = $1(@1) / $3(@3); } + | '+' cdf_expr %prec NEG { $$ = $2(@2); } + | '-' cdf_expr %prec NEG { $$ = negate($2(@2)); } + | '(' cdf_bool_expr ')' { $$ = $2(@2); } | cdf_factor ; @@ -555,7 +602,7 @@ cdf_factor: NAME { if( ! scanner_parsing() ) { yywarn("CDF skipping: no such variable '%s' (ignored)", $1); } else { - yyerror("CDF syntax error: no such variable '%s'", $1); + error_msg(@NAME, "CDF syntax error: no such variable '%s'", $1); } $$ = cdfval_t(); } @@ -565,7 +612,7 @@ cdf_factor: NAME { | NUMSTR { auto value = integer_literal($NUMSTR); if( !value.second ) { - yyerror("CDF error: parsed %s as %ld", + error_msg(@1, "CDF error: parsed %s as %ld", $NUMSTR, value.first); YYERROR; } @@ -585,7 +632,7 @@ copy_impl: copybook_name suppress REPLACING replace_bys copybook_name: COPY name_one { if( -1 == copybook.open($2.string) ) { - yyerror("could not open copybook file " + error_msg(@2, "could not open copybook file " "for '%s'", $2.string); YYERROR; } @@ -594,7 +641,7 @@ copybook_name: COPY name_one { copybook.library($lib.string); if( -1 == copybook.open($src.string) ) { - yyerror("could not open copybook file " + error_msg(@src, "could not open copybook file " "for '%s' in '%'s'", $src.string, $lib.string); YYERROR; } @@ -733,6 +780,13 @@ with: %empty %% +static YYLTYPE cdf_location; + +static YYLTYPE +location_set( const YYLTYPE& loc ) { + return cdf_location = loc; +} + bool // used by cobol1.cc defined_cmd( const char arg[] ) { @@ -778,61 +832,27 @@ cdf_token_str( int token ) { } bool operator==( const cdfval_base_t& lhs, int rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - + gcc_assert( !lhs.string ); return lhs.number == rhs; } bool operator||( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } - + gcc_assert( !lhs.string && !rhs.string ); return lhs.number || rhs.number; } bool operator&&( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } - + gcc_assert( !lhs.string && !rhs.string ); return lhs.number && rhs.number; } cdfval_t operator<( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number < rhs.number); } cdfval_t operator<=( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number <= rhs.number); } @@ -843,17 +863,7 @@ cdfval_t operator==( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { if( !lhs.string && !rhs.string ) { return cdfval_t(lhs.number == rhs.number); } - if( lhs.string ) { - yyerror("incommensurate comparison is FALSE: '%s' = %ld", - lhs.string, rhs.number); - return false; - } - if( rhs.string ) { - yyerror("incommensurate comparison is FALSE: %ld = '%s'", - lhs.number, rhs.string); - return false; - } - cbl_internal_error("'%s' is not an integer", rhs.string); + cbl_internal_error("incommensurate operands"); return false; } @@ -864,96 +874,42 @@ cdfval_t operator!=( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { if( !lhs.string && !rhs.string ) { return cdfval_t(lhs.number != rhs.number); } - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } - cbl_internal_error("'%s' is not an integer", rhs.string); + cbl_internal_error("incommensurate operands"); return false; } cdfval_t operator>=( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number >= rhs.number); } cdfval_t operator>( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number > rhs.number); } cdfval_t operator+( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number + rhs.number); } cdfval_t operator-( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number - rhs.number); } cdfval_t operator*( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number * rhs.number); } cdfval_t operator/( const cdfval_base_t& lhs, const cdfval_base_t& rhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - if( rhs.string ) { - yyerror("'%s' is not an integer", rhs.string); - return false; - } + gcc_assert( !lhs.string && !rhs.string ); return cdfval_t(lhs.number / rhs.number); } cdfval_t negate( cdfval_base_t lhs ) { - if( lhs.string ) { - yyerror("'%s' is not an integer", lhs.string); - return false; - } - + gcc_assert( !lhs.string ); lhs.number = -lhs.number; return lhs; } @@ -965,9 +921,6 @@ static int ydflex(void) { return yylex(); } -#undef yyerror -#include "cbldiag.h" - bool cdf_value( const char name[], cdfval_t value ) { auto p = dictionary.find(name); @@ -986,3 +939,19 @@ cdf_value( const char name[] ) { return &p->second; } + +static bool +verify_integer( const YDFLTYPE& loc, const cdfval_base_t& val ) { + if( val.string ) { + error_msg(loc, "'%s' is not an integer", val.string); + return false; + } + return true; +} + +cdfval_base_t& +cdfval_base_t::operator()( const YDFLTYPE& loc ) { + static cdfval_t zero(0); + return verify_integer(loc, *this) ? *this : zero; +} + diff --git a/gcc/cobol/cdfval.h b/gcc/cobol/cdfval.h index 503e4507a15a..0b45820be117 100644 --- a/gcc/cobol/cdfval.h +++ b/gcc/cobol/cdfval.h @@ -38,10 +38,12 @@ bool scanner_parsing(); +struct YDFLTYPE; struct cdfval_base_t { bool off; const char *string; int64_t number; + cdfval_base_t& operator()( const YDFLTYPE& loc ); }; struct cdf_arg_t { diff --git a/gcc/cobol/lexio.h b/gcc/cobol/lexio.h index d7354b79deb8..da1eaf6a710a 100644 --- a/gcc/cobol/lexio.h +++ b/gcc/cobol/lexio.h @@ -128,8 +128,8 @@ struct YYLTYPE # define YYLTYPE_IS_TRIVIAL 1 #endif -void location_dump( const char func[], int line, - const char tag[], const YYLTYPE& loc); +// void location_dump( const char func[], int line, +// const char tag[], const YYLTYPE& loc); struct filespan_t : public bytespan_t { char *cur, *eol, *quote; diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h index c071d8f316e2..ab62fc6057be 100644 --- a/gcc/cobol/scan_ante.h +++ b/gcc/cobol/scan_ante.h @@ -364,6 +364,8 @@ static void level_found() { yyless(n); \ } while(0) +void cdf_location_set(YYLTYPE loc); + static void update_location() { YYLTYPE loc = { @@ -379,6 +381,8 @@ update_location() { yylloc = loc; + cdf_location_set(loc); + if( getenv(__func__) ) { location_dump(__func__, __LINE__, "yylloc", yylloc); } diff --git a/gcc/cobol/scan_post.h b/gcc/cobol/scan_post.h index 4069e2ac4492..00db3e278ccd 100644 --- a/gcc/cobol/scan_post.h +++ b/gcc/cobol/scan_post.h @@ -258,7 +258,7 @@ prelex() { while( is_cdf_token(token) ) { if( ! run_cdf(token) ) { - yyerror( ">>CDF parser failed" ); + dbgmsg( ">>CDF parser failed" ); return NO_CONDITION; } // Return the CDF's discarded lookahead token, if extant. diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index a0c7f748c693..1421170adfd2 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -2196,12 +2196,17 @@ struct YYLTYPE # define YYLTYPE_IS_TRIVIAL 1 const YYLTYPE& cobol_location(); -void gcc_location_set( const YYLTYPE& loc ); +////void gcc_location_set( const YYLTYPE& loc ); +#endif + +template <typename LOC> +void gcc_location_set( const LOC& loc ); + +template <typename LOC> void location_dump( const char func[], int line, - const char tag[], const YYLTYPE& loc); + const char tag[], const LOC& loc); -#endif // This is slightly oddball. This is an entry point in the charutf8.cc module. // It's the only entry point in the module, and so it seemed to me wasteful to diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc index 695c3e18c0a8..eda924fbd68d 100644 --- a/gcc/cobol/util.cc +++ b/gcc/cobol/util.cc @@ -2071,8 +2071,9 @@ cobol_filename_restore( bool scanning ) { static location_t token_location; +template <typename LOC> void -gcc_location_set( const YYLTYPE& loc ) { +gcc_location_set( const LOC& loc ) { token_location = linemap_line_start( line_table, loc.last_line, 80 ); token_location = linemap_position_for_column( line_table, loc.first_column); if( getenv(__func__) ) { @@ -2080,14 +2081,6 @@ gcc_location_set( const YYLTYPE& loc ) { } } -void -location_dump( const char func[], int line, const char tag[], const YYLTYPE& loc) { - if( yy_flex_debug || yydebug ) - fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n", - func, line, tag, - loc.first_line, loc.first_column, loc.last_line, loc.last_column); -} - #ifdef NDEBUG # define verify_format(M) #else @@ -2137,6 +2130,15 @@ ydferror( const char gmsgid[], ... ) { extern int yychar; extern YYLTYPE yylloc; + +struct YDFLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; + /* * temp_loc_t is a hack in lieu of "%define parse.error custom". When * instantiated, if there is a lookahead token (or one is provided), it sets @@ -2154,6 +2156,12 @@ class temp_loc_t : protected YYLTYPE { temp_loc_t( const YYLTYPE& loc) : orig(token_location) { gcc_location_set(loc); } + temp_loc_t( const YDFLTYPE& loc) : orig(token_location) { + YYLTYPE lloc = { + loc.first_line, loc.first_column, + loc.last_line, loc.last_column }; + gcc_location_set(lloc); + } ~temp_loc_t() { if( orig != token_location ) { token_location = orig; @@ -2161,8 +2169,22 @@ class temp_loc_t : protected YYLTYPE { } }; +// These uses of the error_msg function are never invoked, but encourage the +// compiler to instantiate the templates. +namespace none { + void foo() { + error_msg(YYLTYPE(), "fake"); + error_msg(YDFLTYPE(), "also fake"); + gcc_location_set(YYLTYPE()); + gcc_location_set(YDFLTYPE()); + location_dump("also", 0, "also", YYLTYPE()); + location_dump("fake", 0, "fake", YDFLTYPE()); + } +}; + +template <typename LOC> void -error_msg( const YYLTYPE& loc, const char gmsgid[], ... ) { +error_msg( const LOC& loc, const char gmsgid[], ... ) { temp_loc_t looker(loc); verify_format(gmsgid); parse_error_inc(); @@ -2176,6 +2198,25 @@ error_msg( const YYLTYPE& loc, const char gmsgid[], ... ) { global_dc->end_group(); } +template <typename LOC> +void +location_dump( const char func[], int line, const char tag[], const LOC& loc) { + if( yy_flex_debug || yydebug ) + fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n", + func, line, tag, + loc.first_line, loc.first_column, loc.last_line, loc.last_column); +} + +void +cdf_location_set(YYLTYPE loc) { + extern YDFLTYPE ydflloc; + + ydflloc.first_line = loc.first_line; + ydflloc.first_column = loc.first_column; + ydflloc.last_line = loc.last_line; + ydflloc.last_column = loc.last_column; +} + void yyerror( const char gmsgid[], ... ) { temp_loc_t looker; -- GitLab