[gcc r17-3523] cobol: Allow larger REDEFINES for -dialect ibm.

"James K. Lowden via Gcc-cvs" <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:4918feee536ef3ef5431f87f0b314f6b03378981

commit r17-3523-g4918feee536ef3ef5431f87f0b314f6b03378981
Author: James K. Lowden <[email protected]>
Date:   Thu Aug 20 17:58:09 2026 -0400

    cobol: Allow larger REDEFINES for -dialect ibm.
    
    ISO prohibits B REDEFINES A if B is larger than A, unless A is 01
    level and not external.  IBM and others do not impose the 01 restriction.
    
    Also simplify and correct how -preprocess parses its argument.
    
    gcc/cobol/ChangeLog:
    
            * cbldiag.h (enum cbl_diag_id_t): Define IsoRedefinesGrow.
            * cobol1.cc (cobol_langhook_handle_option): Handle Wredefines-grow.
            * lang-specs.h: Same.
            * lang.opt: Same.
            * lexio.cc (preprocess_filter_add): Use xstrdup, not std::vector.
            * messages.cc: Quell Wredefines-grow with -dialect ibm.
            * parse_ante.h (valid_redefine): Conditional message.

Diff:
---
 gcc/cobol/cbldiag.h    |  1 +
 gcc/cobol/cobol1.cc    |  4 ++++
 gcc/cobol/lang-specs.h |  1 +
 gcc/cobol/lang.opt     |  5 +++++
 gcc/cobol/lexio.cc     |  9 ++++-----
 gcc/cobol/messages.cc  |  6 ++++--
 gcc/cobol/parse_ante.h | 18 +++++++++---------
 7 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/gcc/cobol/cbldiag.h b/gcc/cobol/cbldiag.h
index 5f88e15563a6..c05bfde7f39f 100644
--- a/gcc/cobol/cbldiag.h
+++ b/gcc/cobol/cbldiag.h
@@ -189,6 +189,7 @@ enum cbl_diag_id_t : uint64_t {
   IbmVolatileW,  // dialect warning for ignored syntax
 
   IsoAssignFile,
+  IsoRedefinesGrow,
   IsoResume,
 
   MfAssignExternal,
diff --git a/gcc/cobol/cobol1.cc b/gcc/cobol/cobol1.cc
index eedaf600440a..79c6d507247e 100644
--- a/gcc/cobol/cobol1.cc
+++ b/gcc/cobol/cobol1.cc
@@ -645,6 +645,10 @@ cobol_langhook_handle_option (size_t scode,
           cobol_warning(MfRedefinesFirst, redefines_first, warning_as_error);
           return true;
 
+        case OPT_Wredefines_grow:
+          cobol_warning(IsoRedefinesGrow, redefines_grow, warning_as_error);
+          return true;
+
         case OPT_Wreturning_number:
           cobol_warning(MfReturningNum, returning_number, warning_as_error);
           return true;
diff --git a/gcc/cobol/lang-specs.h b/gcc/cobol/lang-specs.h
index 272ef480b6ae..701a1d1a07a8 100644
--- a/gcc/cobol/lang-specs.h
+++ b/gcc/cobol/lang-specs.h
@@ -91,6 +91,7 @@
 	"%{Wprocedure-pointer} %{Wno-procedure-pointer} "
 	"%{Wreplace-error} %{Wno-replace-error} "
 	"%{Wredefines-first} %{Wno-redefines-first} "
+	"%{Wredefines-grow} %{Wno-redefines-grow} "
 	"%{Wreturning-number} %{Wno-returning-number} "
 	"%{Wsegment-error} %{Wno-segment-error} "
 	"%{Wsegment-negative} %{Wno-segment-negative} "
diff --git a/gcc/cobol/lang.opt b/gcc/cobol/lang.opt
index 9e2f989b2626..8b0a575d1183 100644
--- a/gcc/cobol/lang.opt
+++ b/gcc/cobol/lang.opt
@@ -274,6 +274,11 @@ Wsegment
 Cobol Warning Var(cobol_segment, 1) Init(1)
 Warn if SECTION segments are used.
 
+; IsoRedefinesGrow, "-Wredefines-grow"
+Wredefines-grow
+Cobol Warning Var(redefines_grow, 1) Init(1)
+Warn if REDEFINES data item is larger than the redefined.
+
 ; IsoResume
 Wcobol-resume
 Cobol Warning Var(cobol_resume, 1) Init(1)
diff --git a/gcc/cobol/lexio.cc b/gcc/cobol/lexio.cc
index d4cb4a258f3c..f31f707ad02a 100644
--- a/gcc/cobol/lexio.cc
+++ b/gcc/cobol/lexio.cc
@@ -1443,12 +1443,11 @@ preprocess_filter_add( const char input[] ) {
   size_t pos = filter.find(",");
 
   if( pos != filter.npos ) {
-    std::vector<char> others( filter.size() - pos, '\0' );
-    std::copy( filter.begin() + pos + 1, filter.end(), others.begin() );
+    std::string args( filter.begin() + pos + 1, filter.end() );
     filter.resize(pos);
-    char *optstr = others.data();
-    for( char *opt = optstr + 1; (opt = strtok(opt, ",")); opt = NULL ) {
-      options.push_back(opt);
+
+    for( char *arg = xstrdup(args.c_str()); (arg = strtok(arg, ",")); arg = NULL ) {
+      options.push_back(arg);
     }
   }
 
diff --git a/gcc/cobol/messages.cc b/gcc/cobol/messages.cc
index e55ab194dd79..eff05f98e442 100644
--- a/gcc/cobol/messages.cc
+++ b/gcc/cobol/messages.cc
@@ -137,10 +137,12 @@ std::set<cbl_diag_t> cbl_diagnostics {
   { IbmVolatileE, "-Wcobol-volatile", diagnostics::kind::error, dialect_ibm_e },
   { IbmVolatileW, "-Wcobol-volatile", diagnostics::kind::warning, dialect_ibm_e },
 
-  // RESUME not supported by IBM
-  { IsoResume, "-Wcobol-resume", diagnostics::kind::error, dialect_ibm_e },
   // IBM, MF, and GNU all support ASSIGN TO filename, so we keep mum. 
   { IsoAssignFile, "-Wassign-file", diagnostics::kind::ignored, dialect_ibm_mf_gnu },
+  // ISO says for B REDEFINES A, Length(B) <= Length(A), others disagree
+  { IsoRedefinesGrow, "-Wredefines-grow", diagnostics::kind::error, dialect_ibm_mf_gnu },
+  // RESUME not supported by IBM
+  { IsoResume, "-Wcobol-resume", diagnostics::kind::error, dialect_ibm_e },
 
   { MfAnyLength, "-Wany-length", diagnostics::kind::error, dialect_mf_gnu },
   { MfAssignExternal, "-Wassign-external", diagnostics::kind::error, dialect_mf_gnu },
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index 243f43bbf1e7..2dff569a2b57 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -3145,8 +3145,6 @@ valid_redefine( const cbl_loc_t& loc,
             orig->level_str(), orig->name);
     return false;
   }
-  // We don't know about the redefining group until it's completely defined.
-
   /*
    * 8) The storage area required for the subject of the entry
    * shall not be larger than the storage area required for the
@@ -3159,13 +3157,15 @@ valid_redefine( const cbl_loc_t& loc,
       if( orig->level > 1 || orig->has_attr(external_e) ) {
         dbgmsg( "size error orig:  %s", field_str(orig) );
         dbgmsg( "size error redef: %s", field_str(field) );
-        error_msg(loc, "%s (%s size %u) larger than REDEFINES %s (%s size %u)",
-                  field->name,
-                  3 + cbl_field_type_str(field->type),
-                  field->size()/field->codeset.stride(),
-                  orig->name,
-                  3 + cbl_field_type_str(orig->type),
-                  orig->size()/field->codeset.stride() );
+        if( ! dialect_ok(loc, IsoRedefinesGrow, "REDEFINES larger") ) {
+          error_msg(loc, "%qs (%s size %u) larger than REDEFINES %qs (%s size %u)",
+                    field->name,
+                    3 + cbl_field_type_str(field->type),
+                    field->size()/field->codeset.stride(),
+                    orig->name,
+                    3 + cbl_field_type_str(orig->type),
+                    orig->size()/field->codeset.stride() );
+        }
       }
     }
   }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.