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?
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