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

Paul Eggert <[email protected]>
Newsgroups gmane.comp.lib.gnulib.bugs
Organization UCLA Computer Science Department
Message-ID <[email protected]>
On 2026-08-24 13:23, Bruno Haible wrote:
> As far as I can see, your patch will have the effect that
>    gettext (some_function_that_returns_a_string ())
> will produce a syntax error in C++ mode.
> 
> Am I correct?
Sounds right. Would the attached (untested) patch address the C++ issue?
gettext.diff (text/x-patch, 5.8 KB)
diff --git a/lib/gettext.h b/lib/gettext.h
index 8ae3885fd7..5b7eb708d8 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -59,6 +59,14 @@
 #  endif
 # endif
 
+/* Like the C cast ((type) (expr)), but do only the conversion that
+   an ordinary function call argument would do.  */
+#ifdef __cplusplus
+# define _LIBGETTEXT_FUNCAST(type, expr) (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
    "warning: format not a string literal, argument types not checked [-Wformat-nonliteral]"
@@ -162,39 +170,43 @@ dcgettext (const char *domain, const char *msgid, int category)
 #  endif
 # elif defined __clang__
 #  undef gettext
-#  define gettext(Msgid) ((const char *) {(Msgid)})
+#  define gettext(Msgid) (_LIBGETTEXT_FUNCAST (const char *, Msgid))
 #  undef dgettext
 #  define dgettext(Domainname, Msgid) \
-     ((void) (const char *) {(Domainname)}, gettext (Msgid))
+     ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), gettext (Msgid))
 #  undef dcgettext
 #  define dcgettext(Domainname, Msgid, Category) \
-     ((void) (int) {(Category)}, dgettext (Domainname, Msgid))
+     ((void) _LIBGETTEXT_FUNCAST (int, Category), dgettext (Domainname, Msgid))
 # else
 /* The conversions to 'const char *' via compound literals serve the purpose
    of producing warnings for invalid uses of the value returned from these
    functions and for invalid-typed Msgid arguments.  */
 #  undef gettext
-#  define gettext(Msgid) ((const char *) {(Msgid)})
+#  define gettext(Msgid) _LIBGETTEXT_FUNCAST (const char *, Msgid)
 /* The conversions via compound literals serve the purpose of producing warnings
    for invalid-typed arguments.  */
 #  undef dgettext
 #  define dgettext(Domainname, Msgid) \
-     ((void) (const char *) {(Domainname)}, gettext (Msgid))
+     ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), gettext (Msgid))
 #  undef dcgettext
 #  define dcgettext(Domainname, Msgid, Category) \
-     ((void) (int) {(Category)}, dgettext (Domainname, Msgid))
+     ((void) _LIBGETTEXT_FUNCAST (int, Category), dgettext (Domainname, Msgid))
 # endif
 
 # if (defined __GNUC__ && defined __cplusplus) || defined __clang__
 #  undef ngettext
 #  define ngettext(Msgid1, Msgid2, N) \
-     ((N) == 1 ? (const char *) {(Msgid1)} : (const char *) {(Msgid2)})
+     ((N) == 1 \
+      ? _LIBGETTEXT_FUNCAST (const char *, Msgid1) \
+      : _LIBGETTEXT_FUNCAST (const char *, Msgid2))
 #  undef dngettext
 #  define dngettext(Domainname, Msgid1, Msgid2, N) \
-     ((void) (const char *) {(Domainname)}, ngettext (Msgid1, Msgid2, N))
+     ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \
+      ngettext (Msgid1, Msgid2, N))
 #  undef dcngettext
 #  define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
-     ((void) (int) {(Category)}, dngettext (Domainname, Msgid1, Msgid2, N))
+     ((void) _LIBGETTEXT_FUNCAST (int, Category), \
+      dngettext (Domainname, Msgid1, Msgid2, N))
 # elif defined __GNUC__ && !defined __cplusplus
 /* Silence -Wuseless-cast warnings.  */
 #  if __GNUC__ >= 14
@@ -202,13 +214,17 @@ dcgettext (const char *domain, const char *msgid, int category)
 #  endif
 #  undef ngettext
 #  define ngettext(Msgid1, Msgid2, N) \
-     ((N) == 1 ? (const char *) {(Msgid1)} : (const char *) {(Msgid2)})
+     ((N) == 1 \
+      ? _LIBGETTEXT_FUNCAST (const char *, Msgid1) \
+      : _LIBGETTEXT_FUNCAST (const char *, Msgid2))
 #  undef dngettext
 #  define dngettext(Domainname, Msgid1, Msgid2, N) \
-     ((void) (const char *) {(Domainname)}, ngettext (Msgid1, Msgid2, N))
+     ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \
+      ngettext (Msgid1, Msgid2, N))
 #  undef dcngettext
 #  define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
-     ((void) (int) {(Category)}, dngettext (Domainname, Msgid1, Msgid2, N))
+     ((void) _LIBGETTEXT_FUNCAST (int, Category), \
+      dngettext (Domainname, Msgid1, Msgid2, N))
 # else
 /* The conversions to 'const char *' via compound literals serve the purpose
    of producing warnings for invalid uses of the value returned from these
@@ -216,26 +232,30 @@ dcgettext (const char *domain, const char *msgid, int category)
 #  undef ngettext
 #  define ngettext(Msgid1, Msgid2, N) \
      ((N) == 1 \
-      ? ((void) (Msgid2), (const char *) {(Msgid1)}) \
-      : ((void) (Msgid1), (const char *) {(Msgid2)}))
+      ? ((void) (Msgid2), _LIBGETTEXT_FUNCAST (const char *, Msgid1)) \
+      : ((void) (Msgid1), _LIBGETTEXT_FUNCAST (const char *, Msgid2)))
 /* The conversions via compound literals serve the purpose of producing warnings
    for invalid-typed arguments.  */
 #  undef dngettext
 #  define dngettext(Domainname, Msgid1, Msgid2, N) \
-     ((void) (const char *) {(Domainname)}, ngettext (Msgid1, Msgid2, N))
+     ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \
+      ngettext (Msgid1, Msgid2, N))
 #  undef dcngettext
 #  define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
-     ((void) (int) {(Category)}, dngettext (Domainname, Msgid1, Msgid2, N))
+     ((void) _LIBGETTEXT_FUNCAST (int, Category), \
+      dngettext (Domainname, Msgid1, Msgid2, N))
 # endif
 
 # undef textdomain
-# define textdomain(Domainname) ((const char *) {(Domainname)})
+# define textdomain(Domainname) _LIBGETTEXT_FUNCAST (const char *, Domainname)
 # undef bindtextdomain
 # define bindtextdomain(Domainname, Dirname) \
-    ((void) (const char *) {(Domainname)}, (const char *) {(Dirname)})
+    ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \
+     _LIBGETTEXT_FUNCAST (const char *, Dirname))
 # undef bind_textdomain_codeset
 # define bind_textdomain_codeset(Domainname, Codeset) \
-    ((void) (const char *) {(Domainname)}, (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.