Re: [PATCH] gettext: more-consistent no-op macros

Bruno Haible via Gnulib discussion list <[email protected]>
Newsgroups gmane.comp.lib.gnulib.bugs
Message-ID <6537901.uXWc14spt3@cagnes>
Paul Eggert wrote:
> > Why not
> > 
> >     #ifdef __cplusplus
> >     # define _LIBGETTEXT_FUNCAST(type, expr) static_cast<type> (expr)
> 
> Sounds good, thanks. I installed the attached to do that, and to try to simplify the code a bit.

With an extended test case, I see compilation errors:

   ================================ foo.c ================================
   #include <stdio.h>
   #include "gettext.h"
   extern const char *some_computed_string (void);

   void foo (int n)
   {
     textdomain ("pkg");
     bindtextdomain ("pkg", "/usr/share/locale");
     bind_textdomain_codeset ("pkg", "UTF-8");

     printf (gettext ("foo %d"), n);
     printf (dgettext ("toto", "foo %d"), n);
     printf (dcgettext ("toto", "foo %d", LC_MESSAGES), n);
     printf (ngettext ("foo %d", "bar %d", n), n);
     printf (dngettext ("toto", "foo %d", "bar %d", n), n);
     printf (dcngettext ("toto", "foo %d", "bar %d", n, LC_MESSAGES), n);

     printf ("%s", gettext ("between 7% & 19%."));
     printf ("%s", dgettext ("toto", "between 7% & 19%."));
     printf ("%s", dcgettext ("toto", "between 7% & 19%.", LC_MESSAGES));

     printf (gettext (some_computed_string ()));
     printf (dgettext ("toto", some_computed_string ()));
     printf (dcgettext ("toto", some_computed_string (), LC_MESSAGES));
   }
   =======================================================================

$ gcc -Wall -Wformat=2 -S foo.c
In file included from foo.c:2:
foo.c: In function ‘foo’:
/GNULIB/gnulib-git/lib/gettext.h:68:44: warning: value computed is not used [-Wunused-value]
   68 | #   define _LIBGETTEXT_FUNCAST(type, expr) (type) {(expr)}
      |                                            ^
/GNULIB/gnulib-git/lib/gettext.h:212:33: note: in expansion of macro ‘_LIBGETTEXT_FUNCAST’
  212 | # define textdomain(Domainname) _LIBGETTEXT_FUNCAST (const char *, Domainname)
      |                                 ^~~~~~~~~~~~~~~~~~~
foo.c:7:6: note: in expansion of macro ‘textdomain’
    7 |      textdomain ("pkg");
      |      ^~~~~~~~~~
/GNULIB/gnulib-git/lib/gettext.h:219:13: error: implicit declaration of function ‘_LIBGETTEXT_FUNCAT’ [-Wimplicit-function-declaration]
  219 |     ((void) _LIBGETTEXT_FUNCAT (const char *, Domainname), \
      |             ^~~~~~~~~~~~~~~~~~
foo.c:9:6: note: in expansion of macro ‘bind_textdomain_codeset’
    9 |      bind_textdomain_codeset ("pkg", "UTF-8");
      |      ^~~~~~~~~~~~~~~~~~~~~~~

$ clang -Wall -Wformat=2 -S foo.c
foo.c:9:6: error: call to undeclared function '_LIBGETTEXT_FUNCAT'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    9 |      bind_textdomain_codeset ("pkg", "UTF-8");
      |      ^
/GNULIB/gnulib-git/lib/gettext.h:219:13: note: expanded from macro 'bind_textdomain_codeset'
  219 |     ((void) _LIBGETTEXT_FUNCAT (const char *, Domainname), \
      |             ^

Let me fix that.


2026-08-26  Bruno Haible  <[email protected]>

	gettext-h: Fix compilation error (regression 2026-08-24).
	* lib/gettext.h: Update old comments.
	(_LIBGETTEXT_FUNCAST): Correct indentation.
	(bind_textdomain_codeset): Fix typo.

diff --git a/lib/gettext.h b/lib/gettext.h
index 521d69e6b0..68826302c3 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -42,9 +42,7 @@
 /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
    chokes if dcgettext is defined as a macro.  So include it now, to make
    later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
-   as well because people using "gettext.h" will not include <libintl.h>,
-   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
-   is OK.  */
+   as well because people using "gettext.h" will not include <libintl.h>.  */
 # if defined(__sun)
 #  include <locale.h>
 # endif
@@ -62,11 +60,11 @@
 /* Like the C cast ((type) (expr)), but do only conversions that an
    ordinary assignment would do.  This can diagnose invalid arguments
    better than a cast would.  */
-#  ifdef __cplusplus
-#   define _LIBGETTEXT_FUNCAST(type, expr) static_cast <type> (expr)
-#  else
-#   define _LIBGETTEXT_FUNCAST(type, expr) (type) {(expr)}
-#  endif
+# ifdef __cplusplus
+#  define _LIBGETTEXT_FUNCAST(type, expr) static_cast <type> (expr)
+# else
+#  define _LIBGETTEXT_FUNCAST(type, expr) (type) {(expr)}
+# endif
 
 /* Disabled NLS.  */
 /* When gcc is used with option -Wformat=2, we need to silence
@@ -84,17 +82,32 @@
    ================================ foo.c ================================
    #include <stdio.h>
    #include "gettext.h"
+   extern const char *some_computed_string (void);
+
    void foo (int n)
    {
+     textdomain ("pkg");
+     bindtextdomain ("pkg", "/usr/share/locale");
+     bind_textdomain_codeset ("pkg", "UTF-8");
+
      printf (gettext ("foo %d"), n);
      printf (dgettext ("toto", "foo %d"), n);
      printf (dcgettext ("toto", "foo %d", LC_MESSAGES), n);
      printf (ngettext ("foo %d", "bar %d", n), n);
      printf (dngettext ("toto", "foo %d", "bar %d", n), n);
      printf (dcngettext ("toto", "foo %d", "bar %d", n, LC_MESSAGES), n);
+
+     printf ("%s", gettext ("between 7% & 19%."));
+     printf ("%s", dgettext ("toto", "between 7% & 19%."));
+     printf ("%s", dcgettext ("toto", "between 7% & 19%.", LC_MESSAGES));
+
+     printf (gettext (some_computed_string ()));
+     printf (dgettext ("toto", some_computed_string ()));
+     printf (dcgettext ("toto", some_computed_string (), LC_MESSAGES));
    }
    =======================================================================
    $CC -Wformat=2 -S foo.c
+   $CC -Wformat=2 -S -x c++ foo.c
  */
 # if defined __GNUC__ && !defined __clang__ && !defined __cplusplus
 /* The return type 'const char *' serves the purpose of producing warnings
@@ -216,8 +229,8 @@ dcgettext (const char *domain, const char *msgid, int category)
      _LIBGETTEXT_FUNCAST (const char *, Dirname))
 # undef bind_textdomain_codeset
 # define bind_textdomain_codeset(Domainname, Codeset) \
-    ((void) _LIBGETTEXT_FUNCAT (const char *, Domainname), \
-     _LIBGETTEXT_FUNCAT (const char *, Codeset))
+    ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \
+     _LIBGETTEXT_FUNCAST (const char *, Codeset))
 #endif
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.