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