Change some uses of unreachable() to affirm(false),
so that we would get an abort in normal builds.
This is safer than unreachable() which results in undefined behavior.
See commit v9.8-27-ge661c7a52 for a real case of this.

Uses of unreachable() should be provably unreachable, and trivially so.
Trivial cases: e.g. after error(NON_ZERO, ...) etc,
or a fully handled switch on enum (proved with -Wswitch-enum).

Note unreachable() can be defined to exit with -funreachable-traps,
but it's better to use standard build options and distinguish the
different classes of "unreachable" in code.  Also clang (22) doesn't
seem to support the -funreachable-traps option.

Note we prefer affirm to abort, since it has better diagnostics in the
normal case and better performance with -DNDEBUG.
and prefer affirm to assert, as it allows for better static
checking when compiling with -DNDEBUG.
Neither of these apply to affirm(false),
but we avoid assert for consistency.

* gl/lib/mbbuf.h: s/unreachable/affirm(false)/.
* src/copy-file-data.c: Likewise.
* src/copy.c: Likewise.
* src/cut.c: Likewise.
* src/ls.c: Likewise.
* src/numfmt.c: Likewise.
* src/od.c: Likewise.
* src/stdbuf.c: Likewise.
* src/sync.c: Likewise.
* src/tr.c: Likewise.
* src/tsort.c: Likewise.
* src/wc.c: Likewise.
---
 gl/lib/mbbuf.h       | 7 ++++---
 src/copy-file-data.c | 2 +-
 src/copy.c           | 4 ++--
 src/cut.c            | 2 +-
 src/ls.c             | 4 ++--
 src/numfmt.c         | 3 ++-
 src/od.c             | 2 +-
 src/stdbuf.c         | 2 +-
 src/sync.c           | 3 ++-
 src/tr.c             | 2 +-
 src/tsort.c          | 2 +-
 src/wc.c             | 3 ++-
 12 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/gl/lib/mbbuf.h b/gl/lib/mbbuf.h
index a6289a8ce..626dc737e 100644
--- a/gl/lib/mbbuf.h
+++ b/gl/lib/mbbuf.h
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "assure.h"
 #include "fseterr.h"
 #include "mcel.h"
 #include "idx.h"
@@ -66,7 +67,7 @@ MBBUF_INLINE void
 mbbuf_init (mbbuf_t *mbbuf, char *buffer, idx_t size, FILE *fp)
 {
   if (size < MCEL_LEN_MAX)
-    unreachable ();
+    affirm (false);
   mbbuf->buffer = buffer;
   mbbuf->fp = fp;
   mbbuf->size = size;
@@ -141,7 +142,7 @@ MBBUF_INLINE void
 mbbuf_advance (mbbuf_t *mbbuf, idx_t n)
 {
   if (mbbuf_avail (mbbuf) < n)
-    unreachable ();
+    affirm (false);
   mbbuf->offset += n;
 }
 
@@ -172,7 +173,7 @@ MBBUF_INLINE char *
 mbbuf_char_offset (mbbuf_t *mbbuf, mcel_t g)
 {
   if (mbbuf->offset < g.len)
-    unreachable ();
+    affirm (false);
   return mbbuf->buffer + (mbbuf->offset - g.len);
 }
 
diff --git a/src/copy-file-data.c b/src/copy-file-data.c
index d76ccc0db..9d953fb6f 100644
--- a/src/copy-file-data.c
+++ b/src/copy-file-data.c
@@ -611,7 +611,7 @@ copy_file_data (int ifd, struct stat const *ist, off_t 
ipos, char const *iname,
                            x->reflink_mode != REFLINK_NEVER,
                            iname, oname, &hole_size, debug);
 #else
-      unreachable ();
+      affirm (false);
 #endif
     }
   else
diff --git a/src/copy.c b/src/copy.c
index c1b72dfb4..f3f7a407d 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -144,7 +144,7 @@ copy_debug_string (enum copy_debug_val debug_val)
 
     case COPY_DEBUG_EXTERNAL:
     case COPY_DEBUG_EXTERNAL_INTERNAL:
-    default: unreachable ();
+    default: affirm (false);
     }
 }
 
@@ -161,7 +161,7 @@ copy_debug_sparse_string (enum copy_debug_val debug_val)
 
     case COPY_DEBUG_AVOIDED:
     case COPY_DEBUG_UNSUPPORTED:
-    default: unreachable ();
+    default: affirm (false);
     }
 }
 
diff --git a/src/cut.c b/src/cut.c
index bcf0b3f1b..f4973a2c7 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -1423,7 +1423,7 @@ main (int argc, char **argv)
   switch (cut_mode)
     {
     case CUT_MODE_NONE:
-      unreachable ();
+      affirm (false);
 
     case CUT_MODE_BYTES:
       cut_stream = MB_CUR_MAX <= 1 || !no_split
diff --git a/src/ls.c b/src/ls.c
index 3748a127b..7f3b53541 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2666,7 +2666,7 @@ get_funky_string (char **dest, char const **src, bool 
equals_end,
           break;
 
         case ST_END: case ST_ERROR: default:
-          unreachable ();
+          affirm (false);
         }
     }
 
@@ -3430,7 +3430,7 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,
           break;
 
         case DEREF_UNDEFINED: default:
-          unreachable ();
+          affirm (false);
         }
 
       if (err != 0)
diff --git a/src/numfmt.c b/src/numfmt.c
index 467e5d79b..79feaf2f8 100644
--- a/src/numfmt.c
+++ b/src/numfmt.c
@@ -22,6 +22,7 @@
 #include <langinfo.h>
 
 #include "argmatch.h"
+#include "assure.h"
 #include "c-ctype.h"
 #include "mbswidth.h"
 #include "mcel.h"
@@ -743,7 +744,7 @@ simple_strtod_fatal (enum simple_strtod_error err, char 
const *input_str)
     case SSE_OK_PRECISION_LOSS:
     case SSE_OK:
       /* should never happen - this function isn't called when OK.  */
-      unreachable ();
+      affirm (false);
 
     case SSE_OVERFLOW:
       msgid = N_("value too large to be converted: %s");
diff --git a/src/od.c b/src/od.c
index 265e3d2ee..891037580 100644
--- a/src/od.c
+++ b/src/od.c
@@ -847,7 +847,7 @@ decode_one_format (char const *s_orig, char const *s, char 
const **next,
           break;
 
         default:
-          unreachable ();
+          affirm (false);
         }
 
       /* Prefer INT, prefer LONG to longer types,
diff --git a/src/stdbuf.c b/src/stdbuf.c
index fb7de79b3..785456a98 100644
--- a/src/stdbuf.c
+++ b/src/stdbuf.c
@@ -185,7 +185,7 @@ optc_to_fileno (int c)
       ret = STDOUT_FILENO;
       break;
     default:
-      unreachable ();
+      affirm (false);
     }
 
   return ret;
diff --git a/src/sync.c b/src/sync.c
index 5f94d643f..d03bb00a9 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 
 #include "system.h"
+#include "assure.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "sync"
@@ -143,7 +144,7 @@ sync_arg (enum sync_mode mode, char const *file)
           break;
 #endif
         case MODE_SYNC: default:
-          unreachable ();
+          affirm (false);
         }
 
       if (sync_status < 0)
diff --git a/src/tr.c b/src/tr.c
index df3904f4c..528bee7e9 100644
--- a/src/tr.c
+++ b/src/tr.c
@@ -419,7 +419,7 @@ is_char_class_member (enum Char_class char_class, unsigned 
char c)
       result = c_isxdigit (c);
       break;
     case CC_NO_CLASS: default:
-      unreachable ();
+      affirm (false);
     }
 
   return !! result;
diff --git a/src/tsort.c b/src/tsort.c
index 6ac458924..f6c3463e9 100644
--- a/src/tsort.c
+++ b/src/tsort.c
@@ -255,7 +255,7 @@ search_item (struct item *root, char const *str)
       p = q;
     }
 
-  unreachable ();
+  affirm (false);
 }
 
 /* Record the fact that J precedes K.  */
diff --git a/src/wc.c b/src/wc.c
index 4a31189e6..057b710d6 100644
--- a/src/wc.c
+++ b/src/wc.c
@@ -37,6 +37,7 @@
 #endif
 
 #include "system.h"
+#include "assure.h"
 #include "cpu-supports.h"
 #include "ioblksize.h"
 #include "wc.h"
@@ -990,7 +991,7 @@ main (int argc, char **argv)
       xalloc_die ();
 
     case AI_ERR_OK: default:
-      unreachable ();
+      affirm (false);
     }
 
   /* No arguments on the command line is fine.  That means read from stdin.
-- 
2.55.0


Reply via email to