Hi,

While working on 1e7fe06c, I wished I could make functions generate
compiler warnings:

pg_attribute_deprecated("use pg_mblen_{cstr,range,with_len,unbounded} instead")
extern int     pg_mblen(const char *mbstr);

That'd avoid accidental reintroduction, and also get extension
maintainers' attention. $SUBJECT is C23/C++14's syntax, but you've
long been able to do that with in __attribute__ or __declspec for the
usual suspects so I looked into which compiler versions introduced
that and came up with the attached.

The idea would be to back-patch the deprecation warnings, and delete
the functions in, I guess now, v20.  Then the deprecation notice
facility would always be there for next time we need it.
From b780ba45bbb366406cd2ff42db3c69070ca2b22e Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Wed, 1 Apr 2026 22:20:55 +1300
Subject: [PATCH 1/3] Provide pg_attribute_deprecated("message") macro.

This expands to C23/C++14 [[deprecated("message")]], or equivalent
attributes available since GCC 4.9, Clang 2.9 and MSVC 2008 (and further
back without a message).  It can be placed before a type or function
declaration to trigger compiler warnings when used.

Backpatch-through: 14
---
 src/include/c.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/include/c.h b/src/include/c.h
index 88d13ec9993..67a759b1bf3 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -238,6 +238,21 @@ extern "C++"
 #define pg_attribute_target(...)
 #endif
 
+/*
+ * Support for marking functions and types as deprecated, with a compiler
+ * warning if the function is used.  Precedes a declaration.
+ */
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
+	(defined(__cplusplus) && __cplusplus >= 201402L)
+#define pg_attribute_deprecated(message) [[deprecated(message)]]
+#elif defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 5)
+#define pg_attribute_deprecated(message) __attribute__((deprecated(message)))
+#elif defined(_MSC_VER)
+#define pg_attribute_deprecated(message) __declspec(deprecated(message))
+#else
+#define pg_attribute_deprecated(message)
+#endif
+
 /*
  * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only
  * used in assert-enabled builds, to avoid compiler warnings about unused
-- 
2.53.0

From 57badb2c9b3363ac2f10dd4df222b2bb6c405e82 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Wed, 1 Apr 2026 22:28:25 +1300
Subject: [PATCH 2/3] Mark pg_mblen() and t_is*() as deprecated.

These functions were deprecated by commit 1e7fe06c and shouldn't be used
in new code.  Adding a deprecated attribute will cause warnings in
extension code that is using them.

Backpatch-through: 14
Reviewed-by:
Discussion:
---
 src/include/mb/pg_wchar.h       | 2 +-
 src/include/tsearch/ts_locale.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h
index e1655fe61d6..a3326e365a7 100644
--- a/src/include/mb/pg_wchar.h
+++ b/src/include/mb/pg_wchar.h
@@ -700,7 +700,7 @@ extern int	pg_mblen_range(const char *mbstr, const char *end);
 extern int	pg_mblen_with_len(const char *mbstr, int limit);
 extern int	pg_mblen_unbounded(const char *mbstr);
 
-/* deprecated */
+pg_attribute_deprecated("use pg_mblen_{cstr,range,with_len,unbounded} instead")
 extern int	pg_mblen(const char *mbstr);
 
 extern int	pg_dsplen(const char *mbstr);
diff --git a/src/include/tsearch/ts_locale.h b/src/include/tsearch/ts_locale.h
index 6e2d67ee4a5..90e533eea31 100644
--- a/src/include/tsearch/ts_locale.h
+++ b/src/include/tsearch/ts_locale.h
@@ -60,7 +60,7 @@ extern int	t_is##character_class##_with_len(const char *ptr, int len); \
 extern int	t_is##character_class##_cstr(const char *ptr); \
 extern int	t_is##character_class##_unbounded(const char *ptr); \
 \
-/* deprecated */ \
+pg_attribute_deprecated("use t_isXXX_{cstr,with_len,unbounded} instead") \
 extern int	t_is##character_class(const char *ptr);
 
 GENERATE_T_ISCLASS_DECL(alnum);
-- 
2.53.0

From 477cf8ec1ae9ef333988c0dcd48a20d00eacd93b Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Wed, 1 Apr 2026 23:24:33 +1300
Subject: [PATCH 3/3] Remove pg_mblen() and related functions.

pg_mblen() was unsafe and declared deprecated in all release branches,
and can now removed in master.  The t_is*() functions were less unsafe,
but needed to know which pg_mblen_XXX() replacement to call so they also
gained parallel replacements.

Reviewed-by:
Discussion:
---
 src/backend/tsearch/ts_locale.c | 12 ------------
 src/backend/utils/mb/mbutils.c  | 10 ----------
 src/include/mb/pg_wchar.h       |  3 ---
 src/include/tsearch/ts_locale.h |  9 +--------
 4 files changed, 1 insertion(+), 33 deletions(-)

diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c
index df02ffb12fd..12ef3d11b32 100644
--- a/src/backend/tsearch/ts_locale.c
+++ b/src/backend/tsearch/ts_locale.c
@@ -41,18 +41,6 @@ int \
 t_is##character_class##_cstr(const char *ptr) \
 { \
 	return t_is##character_class##_with_len(ptr, pg_mblen_cstr(ptr)); \
-} \
-/* ptr shall point to a string with pre-validated encoding */ \
-int \
-t_is##character_class##_unbounded(const char *ptr) \
-{ \
-	return t_is##character_class##_with_len(ptr, pg_mblen_unbounded(ptr)); \
-} \
-/* historical name for _unbounded */ \
-int \
-t_is##character_class(const char *ptr) \
-{ \
-	return t_is##character_class##_unbounded(ptr); \
 }
 
 GENERATE_T_ISCLASS_DEF(alnum)
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 78f4d5e202c..08d80f2c36f 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -1143,16 +1143,6 @@ pg_mblen_unbounded(const char *mbstr)
 	return length;
 }
 
-/*
- * Historical name for pg_mblen_unbounded().  Should not be used and will be
- * removed in a later version.
- */
-int
-pg_mblen(const char *mbstr)
-{
-	return pg_mblen_unbounded(mbstr);
-}
-
 /* returns the display length of a multibyte character */
 int
 pg_dsplen(const char *mbstr)
diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h
index a3326e365a7..e42cf562635 100644
--- a/src/include/mb/pg_wchar.h
+++ b/src/include/mb/pg_wchar.h
@@ -700,9 +700,6 @@ extern int	pg_mblen_range(const char *mbstr, const char *end);
 extern int	pg_mblen_with_len(const char *mbstr, int limit);
 extern int	pg_mblen_unbounded(const char *mbstr);
 
-pg_attribute_deprecated("use pg_mblen_{cstr,range,with_len,unbounded} instead")
-extern int	pg_mblen(const char *mbstr);
-
 extern int	pg_dsplen(const char *mbstr);
 extern int	pg_mbstrlen(const char *mbstr);
 extern int	pg_mbstrlen_with_len(const char *mbstr, int limit);
diff --git a/src/include/tsearch/ts_locale.h b/src/include/tsearch/ts_locale.h
index 90e533eea31..b6a2d29ee3f 100644
--- a/src/include/tsearch/ts_locale.h
+++ b/src/include/tsearch/ts_locale.h
@@ -52,16 +52,9 @@ ts_copychar_cstr(void *dest, const void *src)
 	return ts_copychar_with_len(dest, src, pg_mblen_cstr((const char *) src));
 }
 
-/* Historical macro for the above. */
-#define COPYCHAR ts_copychar_cstr
-
 #define GENERATE_T_ISCLASS_DECL(character_class) \
 extern int	t_is##character_class##_with_len(const char *ptr, int len); \
-extern int	t_is##character_class##_cstr(const char *ptr); \
-extern int	t_is##character_class##_unbounded(const char *ptr); \
-\
-pg_attribute_deprecated("use t_isXXX_{cstr,with_len,unbounded} instead") \
-extern int	t_is##character_class(const char *ptr);
+extern int	t_is##character_class##_cstr(const char *ptr);
 
 GENERATE_T_ISCLASS_DECL(alnum);
 GENERATE_T_ISCLASS_DECL(alpha);
-- 
2.53.0

Reply via email to