Re: useless cast warning

Paul Eggert <[email protected]> Fri, 17 Jul 2026 14:18:17 -0700
Newsgroups gmane.comp.lib.gnulib.bugs,gmane.emacs.devel
Organization UCLA Computer Science Department
Message-ID <[email protected]>
On 2026-07-17 00:28, Eli Zaretskii wrote:
>> Date: Fri, 17 Jul 2026 09:09:02 +0200
>> From: Thomas Klausner <[email protected]>
>>
>> Hi!
>>
>> When compiling emacs git head on NetBSD, I see:
>>
>> getopt1.c: In function 'rpl_getopt_long':
>> getopt1.c:31:34: warning: useless cast to type 'char **' [-Wuseless-cast]
>>     31 |   return _getopt_internal (argc, (char **) argv, options, long_options,
>>        |                                  ^
>> getopt1.c: In function 'rpl_getopt_long_only':
>> getopt1.c:54:34: warning: useless cast to type 'char **' [-Wuseless-cast]
>>     54 |   return _getopt_internal (argc, (char **) argv, options, long_options,
>>        |                                  ^
> 
> That's likely a Gnulib issue, so I'm adding Paul to the discussion.

Thanks for reporting that. Collin's suggested fix[1] would provoke 
-Wdiscarded-qualifiers on some other platforms, so I instead installed 
the attached patch into Gnulib, and merged recent Gnulib changes into 
Emacs master. Thomas, please give it a try.

[1]: https://lists.gnu.org/r/emacs-devel/2026-07/msg00172.html
gnulib-getopt.patch (text/x-patch, 2.1 KB)
diff --git a/ChangeLog b/ChangeLog
index d1ea69185f..224bcf30b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2026-07-17  Paul Eggert  <[email protected]>
 
+	getopt: port to NetBSD git head gcc -Wuseless cast
+	Problem reported by Thomas Klausner in:
+	https://lists.gnu.org/r/emacs-devel/2026-07/msg00169.html
+	* lib/getopt-pfx-ext.h (__getopt_argv_const_is_empty): New macro,
+	defined to 1 when we define __getopt_argv_const to empty.
+	* lib/getopt1.c (ARGV_CAST): New macro.
+	(getopt_long, getopt_long_only): Use it.
+
 	gendocs: output human-readable file sizes
 	* build-aux/gendocs.sh (calcsize): Output human-readable file
 	size, rather than always size in KiB mislabled as "K bytes".
diff --git a/lib/getopt-pfx-ext.h b/lib/getopt-pfx-ext.h
index db2e27f36c..189598a125 100644
--- a/lib/getopt-pfx-ext.h
+++ b/lib/getopt-pfx-ext.h
@@ -58,6 +58,7 @@
 #ifndef __getopt_argv_const
 # if defined __GETOPT_PREFIX
 #  define __getopt_argv_const /* empty */
+#  define __getopt_argv_const_is_empty 1
 # else
 #  define __getopt_argv_const const
 # endif
diff --git a/lib/getopt1.c b/lib/getopt1.c
index a5f9988828..c127c627ee 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -24,11 +24,19 @@
 #include <getopt.h>
 #include "getopt_int.h"
 
+/* Convert char *__getopt_argv_const * to char ** without provoking
+   gcc -Wuseless-cast when __getopt_argv_const is empty.  */
+#ifdef __getopt_argv_const_is_empty
+# define ARGV_CAST(argv) (argv)
+#else
+# define ARGV_CAST(argv) ((char **) (argv))
+#endif
+
 int
 getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
 	     const struct option *long_options, int *opt_index)
 {
-  return _getopt_internal (argc, (char **) argv, options, long_options,
+  return _getopt_internal (argc, ARGV_CAST (argv), options, long_options,
 			   opt_index, 0, 0);
 }
 
@@ -51,7 +59,7 @@ getopt_long_only (int argc, char *__getopt_argv_const *argv,
 		  const char *options,
 		  const struct option *long_options, int *opt_index)
 {
-  return _getopt_internal (argc, (char **) argv, options, long_options,
+  return _getopt_internal (argc, ARGV_CAST (argv), options, long_options,
 			   opt_index, 1, 0);
 }