public inbox for [email protected]
help / color / mirror / Atom feedMake copyObject work in C++
39+ messages / 7 participants
[nested] [flat]
* Make copyObject work in C++
@ 2025-12-05 14:46 Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
2025-12-08 07:57 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 3 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2025-12-05 14:46 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by using decltype instead of typeof when
including the header in C++.
Realized because of Thomas' not about how much of our headers should
work in C++, and remembering I hit this specific problem myself.
Another approach would be to force the value of HAVE_TYPEOF to 0 if __cplusplus.
Attachments:
[application/x-patch] v1-0001-Make-copyObject-work-in-C.patch (1.3K, 2-v1-0001-Make-copyObject-work-in-C.patch)
download | inline diff:
From 7ce44917fe789e394193ff20e3b88b2e82f96c20 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v1] Make copyObject work in C++
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by using decltype instead of typeof when
including the header in C++.
---
src/include/nodes/nodes.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fb3957e75e5..5a4fa8260f2 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,7 +226,9 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
+#if defined(__cplusplus)
+#define copyObject(obj) ((decltype(obj)) copyObjectImpl(obj))
+#elif defined(HAVE_TYPEOF)
#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
base-commit: 4d936c3fff1ac8dead2cc240ba3da2ed6337257c
--
2.52.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2025-12-07 19:45 ` Tom Lane <[email protected]>
2025-12-08 08:00 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2025-12-08 08:11 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2 siblings, 2 replies; 39+ messages in thread
From: Tom Lane @ 2025-12-07 19:45 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
Jelte Fennema-Nio <[email protected]> writes:
> Calling copyObject fails in C++ with an error like in most setups:
> error: use of undeclared identifier 'typeof'; did you mean 'typeid'
> This is due to the C compiler supporting used to compile postgres
> supporting typeof, but that function actually not being present in the
> C++ compiler. This fixes that by using decltype instead of typeof when
> including the header in C++.
Hmm, this only fixes the one use-case. Admittedly we have only one
use-case, but as soon as we have another we'll have a new problem.
How about instead modifying the macro? Maybe something like this
in c.h (untested):
#ifdef __cplusplus
#undef typeof
#define typeof decltype
#define HAVE_TYPEOF 1
#endif
> Another approach would be to force the value of HAVE_TYPEOF to 0 if __cplusplus.
That would be sad, because we'd lose the type checking ability
of copyObject() in C++ code.
BTW, grepping finds a number of random references to __typeof__ and
__typeof, which probably ought to be updated to be just typeof.
regards, tom lane
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
@ 2025-12-08 08:00 ` Peter Eisentraut <[email protected]>
2025-12-08 14:51 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2025-12-08 08:00 UTC (permalink / raw)
To: Tom Lane <[email protected]>; Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 07.12.25 20:45, Tom Lane wrote:
> Hmm, this only fixes the one use-case. Admittedly we have only one
> use-case, but as soon as we have another we'll have a new problem.
> How about instead modifying the macro? Maybe something like this
> in c.h (untested):
>
> #ifdef __cplusplus
> #undef typeof
> #define typeof decltype
> #define HAVE_TYPEOF 1
> #endif
AFAICT, both gcc and clang support typeof in C++ mode as well. So this
kind of renaming could be confusing.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
2025-12-08 08:00 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2025-12-08 14:51 ` Tom Lane <[email protected]>
2025-12-08 15:31 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Tom Lane @ 2025-12-08 14:51 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
Peter Eisentraut <[email protected]> writes:
> AFAICT, both gcc and clang support typeof in C++ mode as well. So this
> kind of renaming could be confusing.
Hm, if that's true then we should not have to do anything ...
so why is Jelte reporting a problem?
regards, tom lane
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
2025-12-08 08:00 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2025-12-08 14:51 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
@ 2025-12-08 15:31 ` Jelte Fennema-Nio <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2025-12-08 15:31 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Mon, 8 Dec 2025 at 15:51, Tom Lane <[email protected]> wrote:
>
> Peter Eisentraut <[email protected]> writes:
> > AFAICT, both gcc and clang support typeof in C++ mode as well. So this
> > kind of renaming could be confusing.
>
> Hm, if that's true then we should not have to do anything ...
> so why is Jelte reporting a problem?
Seems it's related to -std=c++17 vs -std=gnu++17. I was compiling my
code with the former, which throws the error in question[1]. Compiling
with the latter works fine[2].
So I guess it depends what we want to require from C++ extensions.
Should we require them to compile with gnu extensions? My opinion on
that would be no.
[1]: https://godbolt.org/z/fz567hs1r
[2]: https://godbolt.org/z/cq1se55bn
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
@ 2025-12-08 08:11 ` Jelte Fennema-Nio <[email protected]>
2025-12-14 16:56 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Jelte Fennema-Nio @ 2025-12-08 08:11 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Sun Dec 7, 2025 at 8:45 PM CET, Tom Lane wrote:
> #ifdef __cplusplus
> #undef typeof
> #define typeof decltype
> #define HAVE_TYPEOF 1
> #endif
Went with defining pg_exprtype (pg_typeof already exists). Undefining
typeof seemed a bit heavy-handed. Especially since I think it would be
nice to backport this so C++ extensions can use copyObject directly.
> BTW, grepping finds a number of random references to __typeof__ and
> __typeof, which probably ought to be updated to be just typeof.
Added a follow on patch that starts using pg_exrtype in all those
places.
Attachments:
[text/x-patch] v2-0001-Make-copyObject-work-in-C.patch (2.1K, 2-v2-0001-Make-copyObject-work-in-C.patch)
download | inline diff:
From 5a076be8b919034c7ff469e39a92d76c78590a59 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v2 1/2] Make copyObject work in C++
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by defining pg_exprtype which maps to
typeof or decltype depending on the compiler. While pg_typeof would have
been a more natural name, that one is already taken in our codebase as
the implementation of the pg_typeof UDF.
---
src/include/c.h | 13 +++++++++++++
src/include/nodes/nodes.h | 4 ++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index ccd2b654d45..46a97f11ae7 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -407,6 +407,19 @@
#define unlikely(x) ((x) != 0)
#endif
+/*
+ * pg_exprtype
+ * Get the type of an expression at compile time.
+ *
+ * In C++ we use decltype since typeof is not standard C++, while in C we use
+ * typeof when available.
+ */
+#if defined(__cplusplus)
+#define pg_exprtype(x) decltype(x)
+#elif defined(HAVE_TYPEOF)
+#define pg_exprtype(x) typeof(x)
+#endif
+
/*
* CppAsString
* Convert the argument to a string, using the C preprocessor.
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fb3957e75e5..a8f42431828 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef pg_exprtype
+#define copyObject(obj) ((pg_exprtype(obj)) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
base-commit: 31280d96a64850f5a9a924088890ab43a2905237
--
2.52.0
[text/x-patch] v2-0002-Use-pg_exprtype-instead-of-__typeof__-or-__typeof.patch (3.7K, 3-v2-0002-Use-pg_exprtype-instead-of-__typeof__-or-__typeof.patch)
download | inline diff:
From 62f920e519004d692b14659c5d00546baa6be87c Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 8 Dec 2025 08:13:51 +0100
Subject: [PATCH v2 2/2] Use pg_exprtype instead of __typeof__ or __typeof
The previous commit introduced pg_exprtype. This starts using that in a
few more places.
---
src/include/c.h | 8 ++++----
src/include/utils/relptr.h | 16 ++++------------
2 files changed, 8 insertions(+), 16 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 46a97f11ae7..230ea2d10af 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -987,10 +987,10 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
*/
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
#define AssertVariableIsOfType(varname, typename) \
- StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ StaticAssertStmt(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename))
#define AssertVariableIsOfTypeMacro(varname, typename) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename)))
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
#define AssertVariableIsOfType(varname, typename) \
@@ -1238,11 +1238,11 @@ typedef struct PGAlignedXLogBlock
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), const underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), volatile underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#else
diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
index ea340fee657..dac61b13118 100644
--- a/src/include/utils/relptr.h
+++ b/src/include/utils/relptr.h
@@ -38,16 +38,12 @@
#define relptr_declare(type, relptrtype) \
typedef relptr(type) relptrtype
-#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#ifdef pg_exprtype
#define relptr_access(base, rp) \
(AssertVariableIsOfTypeMacro(base, char *), \
- (__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
+ (pg_exprtype((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
(base) + (rp).relptr_off - 1))
#else
-/*
- * If we don't have __builtin_types_compatible_p, assume we might not have
- * __typeof__ either.
- */
#define relptr_access(base, rp) \
(AssertVariableIsOfTypeMacro(base, char *), \
(void *) ((rp).relptr_off == 0 ? NULL : (base) + (rp).relptr_off - 1))
@@ -72,16 +68,12 @@ relptr_store_eval(char *base, char *val)
}
}
-#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#ifdef pg_exprtype
#define relptr_store(base, rp, val) \
(AssertVariableIsOfTypeMacro(base, char *), \
- AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
+ AssertVariableIsOfTypeMacro(val, pg_exprtype((rp).relptr_type)), \
(rp).relptr_off = relptr_store_eval((base), (char *) (val)))
#else
-/*
- * If we don't have __builtin_types_compatible_p, assume we might not have
- * __typeof__ either.
- */
#define relptr_store(base, rp, val) \
(AssertVariableIsOfTypeMacro(base, char *), \
(rp).relptr_off = relptr_store_eval((base), (char *) (val)))
--
2.52.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Re: Make copyObject work in C++ Tom Lane <[email protected]>
2025-12-08 08:11 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2025-12-14 16:56 ` Jelte Fennema-Nio <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2025-12-14 16:56 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Mon Dec 8, 2025 at 9:11 AM CET, Jelte Fennema-Nio wrote:
> Went with defining pg_exprtype (pg_typeof already exists). Undefining
> typeof seemed a bit heavy-handed. Especially since I think it would be
> nice to backport this so C++ extensions can use copyObject directly.
Rebased version of this patchset after conflicts from 315342ffed.
Attachments:
[text/x-patch] v3-0001-Make-copyObject-work-in-C.patch (2.1K, 2-v3-0001-Make-copyObject-work-in-C.patch)
download | inline diff:
From 4d4e137b4712b48bf3b7c5a19813c1956a28538e Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v3 1/2] Make copyObject work in C++
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by defining pg_exprtype which maps to
typeof or decltype depending on the compiler. While pg_typeof would have
been a more natural name, that one is already taken in our codebase as
the implementation of the pg_typeof UDF.
---
src/include/c.h | 13 +++++++++++++
src/include/nodes/nodes.h | 4 ++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index d2cdc76644c..040f2ffc32b 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -418,6 +418,19 @@
#define unlikely(x) ((x) != 0)
#endif
+/*
+ * pg_exprtype
+ * Get the type of an expression at compile time.
+ *
+ * In C++ we use decltype since typeof is not standard C++, while in C we use
+ * typeof when available.
+ */
+#if defined(__cplusplus)
+#define pg_exprtype(x) decltype(x)
+#elif defined(HAVE_TYPEOF)
+#define pg_exprtype(x) typeof(x)
+#endif
+
/*
* CppAsString
* Convert the argument to a string, using the C preprocessor.
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fb3957e75e5..a8f42431828 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef pg_exprtype
+#define copyObject(obj) ((pg_exprtype(obj)) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
base-commit: c5ae07a90a0f3594e5053a26f3c99b041df427d3
--
2.52.0
[text/x-patch] v3-0002-Use-pg_exprtype-instead-of-typeof.patch (3.1K, 3-v3-0002-Use-pg_exprtype-instead-of-typeof.patch)
download | inline diff:
From 8a4b4749aa87dff7e4e40d2eeb21b84f97811738 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 8 Dec 2025 08:13:51 +0100
Subject: [PATCH v3 2/2] Use pg_exprtype instead of typeof
The previous commit introduced pg_exprtype. This starts using that in a
few more places.
---
src/include/c.h | 8 ++++----
src/include/utils/relptr.h | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 040f2ffc32b..f0800669f09 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -997,10 +997,10 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
*/
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
#define AssertVariableIsOfType(varname, typename) \
- StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ StaticAssertStmt(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename))
#define AssertVariableIsOfTypeMacro(varname, typename) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename)))
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
#define AssertVariableIsOfType(varname, typename) \
@@ -1248,11 +1248,11 @@ typedef struct PGAlignedXLogBlock
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), const underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), volatile underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#else
diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
index 48e394dba71..dac61b13118 100644
--- a/src/include/utils/relptr.h
+++ b/src/include/utils/relptr.h
@@ -38,10 +38,10 @@
#define relptr_declare(type, relptrtype) \
typedef relptr(type) relptrtype
-#ifdef HAVE_TYPEOF
+#ifdef pg_exprtype
#define relptr_access(base, rp) \
(AssertVariableIsOfTypeMacro(base, char *), \
- (typeof((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
+ (pg_exprtype((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
(base) + (rp).relptr_off - 1))
#else
#define relptr_access(base, rp) \
@@ -68,10 +68,10 @@ relptr_store_eval(char *base, char *val)
}
}
-#ifdef HAVE_TYPEOF
+#ifdef pg_exprtype
#define relptr_store(base, rp, val) \
(AssertVariableIsOfTypeMacro(base, char *), \
- AssertVariableIsOfTypeMacro(val, typeof((rp).relptr_type)), \
+ AssertVariableIsOfTypeMacro(val, pg_exprtype((rp).relptr_type)), \
(rp).relptr_off = relptr_store_eval((base), (char *) (val)))
#else
#define relptr_store(base, rp, val) \
--
2.52.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2025-12-08 07:57 ` Peter Eisentraut <[email protected]>
2025-12-08 08:33 ` Re: Make copyObject work in C++ David Geier <[email protected]>
2025-12-09 12:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2 siblings, 2 replies; 39+ messages in thread
From: Peter Eisentraut @ 2025-12-08 07:57 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 05.12.25 15:46, Jelte Fennema-Nio wrote:
> Calling copyObject fails in C++ with an error like in most setups:
>
> error: use of undeclared identifier 'typeof'; did you mean 'typeid'
>
> This is due to the C compiler supporting used to compile postgres
> supporting typeof, but that function actually not being present in the
> C++ compiler. This fixes that by using decltype instead of typeof when
> including the header in C++.
>
> Realized because of Thomas' not about how much of our headers should
> work in C++, and remembering I hit this specific problem myself.
>
> Another approach would be to force the value of HAVE_TYPEOF to 0 if __cplusplus.
In the long run, I would like to change copyObject() to use
typeof_unqual instead, because that handles qualifiers more correctly.
(Currently, copyObject() of a const-qualified pointer results in a
const-qualified pointer, which is nonsensical because the reason you
made the copy is that you can modify it.) See attached patch for an
example. Does C++ have something that is semantically similar to that?
From 1e733f16f116be638cbd4f6a359a01541c9a5d24 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 8 Dec 2025 08:33:18 +0100
Subject: [PATCH] Change copyObject() to use typeof_unqual
The new implementation ensures that the result of copyObject() is not
const-qualified when the input is. This was previously incorrect,
since the point of copyObject() is to make a copy to mutate, but
apparently no code ran into it.
---
config/c-compiler.m4 | 25 +++++++++++++++++++++++
configure | 42 ++++++++++++++++++++++++++++++++++++++
configure.ac | 1 +
meson.build | 24 ++++++++++++++++++++++
src/include/nodes/nodes.h | 4 ++--
src/include/pg_config.h.in | 7 +++++++
6 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 236a59e8536..8ee860c9091 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -160,6 +160,31 @@ if test "$pgac_cv_c_typeof" != no; then
fi])# PGAC_C_TYPEOF
+# PGAC_C_TYPEOF_UNQUAL
+# --------------------
+# Check if the C compiler understands typeof_unqual or a variant. Define
+# HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word.
+#
+AC_DEFUN([PGAC_C_TYPEOF_UNQUAL],
+[AC_CACHE_CHECK(for typeof_unqual, pgac_cv_c_typeof_unqual,
+[pgac_cv_c_typeof_unqual=no
+for pgac_kw in typeof_unqual __typeof_unqual__; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;])],
+[pgac_cv_c_typeof_unqual=$pgac_kw])
+ test "$pgac_cv_c_typeof_unqual" != no && break
+done])
+if test "$pgac_cv_c_typeof_unqual" != no; then
+ AC_DEFINE(HAVE_TYPEOF_UNQUAL, 1,
+ [Define to 1 if your compiler understands `typeof_unqual' or something similar.])
+ if test "$pgac_cv_c_typeof_unqual" != typeof_unqual; then
+ AC_DEFINE_UNQUOTED(typeof_unqual, $pgac_cv_c_typeof_unqual, [Define to how the compiler spells `typeof_unqual'.])
+ fi
+fi])# PGAC_C_TYPEOF_UNQUAL
+
# PGAC_C_TYPES_COMPATIBLE
# -----------------------
diff --git a/configure b/configure
index 3a0ed11fa8e..af856b20f0b 100755
--- a/configure
+++ b/configure
@@ -14787,6 +14787,48 @@ _ACEOF
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeof_unqual" >&5
+$as_echo_n "checking for typeof_unqual... " >&6; }
+if ${pgac_cv_c_typeof_unqual+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ pgac_cv_c_typeof_unqual=no
+for pgac_kw in typeof_unqual __typeof_unqual__; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ pgac_cv_c_typeof_unqual=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$pgac_cv_c_typeof_unqual" != no && break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_c_typeof_unqual" >&5
+$as_echo "$pgac_cv_c_typeof_unqual" >&6; }
+if test "$pgac_cv_c_typeof_unqual" != no; then
+
+$as_echo "#define HAVE_TYPEOF_UNQUAL 1" >>confdefs.h
+
+ if test "$pgac_cv_c_typeof_unqual" != typeof_unqual; then
+
+cat >>confdefs.h <<_ACEOF
+#define typeof_unqual $pgac_cv_c_typeof_unqual
+_ACEOF
+
+ fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
if ${pgac_cv__types_compatible+:} false; then :
diff --git a/configure.ac b/configure.ac
index c2413720a18..8eced24beb5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1676,6 +1676,7 @@ AC_C_INLINE
PGAC_PRINTF_ARCHETYPE
PGAC_C_STATIC_ASSERT
PGAC_C_TYPEOF
+PGAC_C_TYPEOF_UNQUAL
PGAC_C_TYPES_COMPATIBLE
PGAC_C_BUILTIN_CONSTANT_P
PGAC_C_BUILTIN_OP_OVERFLOW
diff --git a/meson.build b/meson.build
index 6e7ddd74683..85b98ad81db 100644
--- a/meson.build
+++ b/meson.build
@@ -2818,6 +2818,30 @@ int main(void)
endif
endforeach
+# Check if the C compiler understands typeof_unqual or a variant. Define
+# HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word.
+foreach kw : ['typeof_unqual', '__typeof_unqual__']
+ if cc.compiles('''
+int main(void)
+{
+ int x = 0;
+ @0@(x) y;
+ y = x;
+ return y;
+}
+'''.format(kw),
+ name: kw,
+ args: test_c_args, include_directories: postgres_inc)
+
+ cdata.set('HAVE_TYPEOF_UNQUAL', 1)
+ if kw != 'typeof_unqual'
+ cdata.set('typeof_unqual', kw)
+ endif
+
+ break
+ endif
+endforeach
+
# Even though restrict is in C99 and should be supported by all
# supported compilers, this indirection is useful because __restrict
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fb3957e75e5..0ac0be1b288 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef HAVE_TYPEOF_UNQUAL
+#define copyObject(obj) ((typeof_unqual(*(obj)) *) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b0b0cfdaf79..503467ca092 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -472,6 +472,10 @@
/* Define to 1 if your compiler understands `typeof' or something similar. */
#undef HAVE_TYPEOF
+/* Define to 1 if your compiler understands `typeof_unqual' or something
+ similar. */
+#undef HAVE_TYPEOF_UNQUAL
+
/* Define to 1 if you have the <uchar.h> header file. */
#undef HAVE_UCHAR_H
@@ -815,3 +819,6 @@
/* Define to how the compiler spells `typeof'. */
#undef typeof
+
+/* Define to how the compiler spells `typeof_unqual'. */
+#undef typeof_unqual
--
2.52.0
Attachments:
[text/plain] 0001-Change-copyObject-to-use-typeof_unqual.patch (5.8K, 2-0001-Change-copyObject-to-use-typeof_unqual.patch)
download | inline diff:
From 1e733f16f116be638cbd4f6a359a01541c9a5d24 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 8 Dec 2025 08:33:18 +0100
Subject: [PATCH] Change copyObject() to use typeof_unqual
The new implementation ensures that the result of copyObject() is not
const-qualified when the input is. This was previously incorrect,
since the point of copyObject() is to make a copy to mutate, but
apparently no code ran into it.
---
config/c-compiler.m4 | 25 +++++++++++++++++++++++
configure | 42 ++++++++++++++++++++++++++++++++++++++
configure.ac | 1 +
meson.build | 24 ++++++++++++++++++++++
src/include/nodes/nodes.h | 4 ++--
src/include/pg_config.h.in | 7 +++++++
6 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 236a59e8536..8ee860c9091 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -160,6 +160,31 @@ if test "$pgac_cv_c_typeof" != no; then
fi])# PGAC_C_TYPEOF
+# PGAC_C_TYPEOF_UNQUAL
+# --------------------
+# Check if the C compiler understands typeof_unqual or a variant. Define
+# HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word.
+#
+AC_DEFUN([PGAC_C_TYPEOF_UNQUAL],
+[AC_CACHE_CHECK(for typeof_unqual, pgac_cv_c_typeof_unqual,
+[pgac_cv_c_typeof_unqual=no
+for pgac_kw in typeof_unqual __typeof_unqual__; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;])],
+[pgac_cv_c_typeof_unqual=$pgac_kw])
+ test "$pgac_cv_c_typeof_unqual" != no && break
+done])
+if test "$pgac_cv_c_typeof_unqual" != no; then
+ AC_DEFINE(HAVE_TYPEOF_UNQUAL, 1,
+ [Define to 1 if your compiler understands `typeof_unqual' or something similar.])
+ if test "$pgac_cv_c_typeof_unqual" != typeof_unqual; then
+ AC_DEFINE_UNQUOTED(typeof_unqual, $pgac_cv_c_typeof_unqual, [Define to how the compiler spells `typeof_unqual'.])
+ fi
+fi])# PGAC_C_TYPEOF_UNQUAL
+
# PGAC_C_TYPES_COMPATIBLE
# -----------------------
diff --git a/configure b/configure
index 3a0ed11fa8e..af856b20f0b 100755
--- a/configure
+++ b/configure
@@ -14787,6 +14787,48 @@ _ACEOF
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeof_unqual" >&5
+$as_echo_n "checking for typeof_unqual... " >&6; }
+if ${pgac_cv_c_typeof_unqual+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ pgac_cv_c_typeof_unqual=no
+for pgac_kw in typeof_unqual __typeof_unqual__; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ pgac_cv_c_typeof_unqual=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$pgac_cv_c_typeof_unqual" != no && break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_c_typeof_unqual" >&5
+$as_echo "$pgac_cv_c_typeof_unqual" >&6; }
+if test "$pgac_cv_c_typeof_unqual" != no; then
+
+$as_echo "#define HAVE_TYPEOF_UNQUAL 1" >>confdefs.h
+
+ if test "$pgac_cv_c_typeof_unqual" != typeof_unqual; then
+
+cat >>confdefs.h <<_ACEOF
+#define typeof_unqual $pgac_cv_c_typeof_unqual
+_ACEOF
+
+ fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
if ${pgac_cv__types_compatible+:} false; then :
diff --git a/configure.ac b/configure.ac
index c2413720a18..8eced24beb5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1676,6 +1676,7 @@ AC_C_INLINE
PGAC_PRINTF_ARCHETYPE
PGAC_C_STATIC_ASSERT
PGAC_C_TYPEOF
+PGAC_C_TYPEOF_UNQUAL
PGAC_C_TYPES_COMPATIBLE
PGAC_C_BUILTIN_CONSTANT_P
PGAC_C_BUILTIN_OP_OVERFLOW
diff --git a/meson.build b/meson.build
index 6e7ddd74683..85b98ad81db 100644
--- a/meson.build
+++ b/meson.build
@@ -2818,6 +2818,30 @@ int main(void)
endif
endforeach
+# Check if the C compiler understands typeof_unqual or a variant. Define
+# HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word.
+foreach kw : ['typeof_unqual', '__typeof_unqual__']
+ if cc.compiles('''
+int main(void)
+{
+ int x = 0;
+ @0@(x) y;
+ y = x;
+ return y;
+}
+'''.format(kw),
+ name: kw,
+ args: test_c_args, include_directories: postgres_inc)
+
+ cdata.set('HAVE_TYPEOF_UNQUAL', 1)
+ if kw != 'typeof_unqual'
+ cdata.set('typeof_unqual', kw)
+ endif
+
+ break
+ endif
+endforeach
+
# Even though restrict is in C99 and should be supported by all
# supported compilers, this indirection is useful because __restrict
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fb3957e75e5..0ac0be1b288 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef HAVE_TYPEOF_UNQUAL
+#define copyObject(obj) ((typeof_unqual(*(obj)) *) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b0b0cfdaf79..503467ca092 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -472,6 +472,10 @@
/* Define to 1 if your compiler understands `typeof' or something similar. */
#undef HAVE_TYPEOF
+/* Define to 1 if your compiler understands `typeof_unqual' or something
+ similar. */
+#undef HAVE_TYPEOF_UNQUAL
+
/* Define to 1 if you have the <uchar.h> header file. */
#undef HAVE_UCHAR_H
@@ -815,3 +819,6 @@
/* Define to how the compiler spells `typeof'. */
#undef typeof
+
+/* Define to how the compiler spells `typeof_unqual'. */
+#undef typeof_unqual
--
2.52.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-08 07:57 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2025-12-08 08:33 ` David Geier <[email protected]>
2025-12-08 08:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: David Geier @ 2025-12-08 08:33 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 08.12.2025 08:57, Peter Eisentraut wrote:
> On 05.12.25 15:46, Jelte Fennema-Nio wrote:
>> Calling copyObject fails in C++ with an error like in most setups:
>>
>> error: use of undeclared identifier 'typeof'; did you mean 'typeid'
>>
>> This is due to the C compiler supporting used to compile postgres
>> supporting typeof, but that function actually not being present in the
>> C++ compiler. This fixes that by using decltype instead of typeof when
>> including the header in C++.
>>
>> Realized because of Thomas' not about how much of our headers should
>> work in C++, and remembering I hit this specific problem myself.
>>
>> Another approach would be to force the value of HAVE_TYPEOF to 0 if
>> __cplusplus.
>
> In the long run, I would like to change copyObject() to use
> typeof_unqual instead, because that handles qualifiers more correctly.
> (Currently, copyObject() of a const-qualified pointer results in a
> const-qualified pointer, which is nonsensical because the reason you
> made the copy is that you can modify it.) See attached patch for an
> example. Does C++ have something that is semantically similar to that?
Since C++11 there's std::remove_const which can be used as
std::remove_const<decltype(type)>::type.
I'm not aware of anything pre C++11, except for rolling your own variant
of std::remove_const via template specialization.
--
David Geier
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-08 07:57 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2025-12-08 08:33 ` Re: Make copyObject work in C++ David Geier <[email protected]>
@ 2025-12-08 08:52 ` Jelte Fennema-Nio <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2025-12-08 08:52 UTC (permalink / raw)
To: David Geier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Mon, 8 Dec 2025 at 09:33, David Geier <[email protected]> wrote:
> Since C++11 there's std::remove_const which can be used as
> std::remove_const<decltype(type)>::type.
>
> I'm not aware of anything pre C++11, except for rolling your own variant
> of std::remove_const via template specialization.
I think depending on C++11 sounds fine, since we're also depending on
C11 and people tend to use much more recent C++ versions than C
versions (so probably we could even require something higher).
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-08 07:57 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2025-12-09 12:58 ` Jelte Fennema-Nio <[email protected]>
1 sibling, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2025-12-09 12:58 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Mon, 8 Dec 2025 at 08:57, Peter Eisentraut <[email protected]> wrote:
> In the long run, I would like to change copyObject() to use
> typeof_unqual instead, because that handles qualifiers more correctly.
> (Currently, copyObject() of a const-qualified pointer results in a
> const-qualified pointer, which is nonsensical because the reason you
> made the copy is that you can modify it.) See attached patch for an
> example. Does C++ have something that is semantically similar to that?
Yes, there's a std::remove_cv, std::remove_const, and std::remove_volatile[1].
[1]: https://en.cppreference.com/w/cpp/types/remove_cv.html
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2025-12-16 12:28 ` Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2025-12-16 12:28 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 05.12.25 15:46, Jelte Fennema-Nio wrote:
> Calling copyObject fails in C++ with an error like in most setups:
>
> error: use of undeclared identifier 'typeof'; did you mean 'typeid'
>
> This is due to the C compiler supporting used to compile postgres
> supporting typeof, but that function actually not being present in the
> C++ compiler. This fixes that by using decltype instead of typeof when
> including the header in C++.
>
> Realized because of Thomas' not about how much of our headers should
> work in C++, and remembering I hit this specific problem myself.
I think it might be good to create a test extension written in C++, like
under src/test/modules/, and sprinkle it with various constructs like
copyObject() and static assertions, and whatever else we find that is
possibly problematic. Then patches like this one would be much easier
to analyze and test and keep working in the future.
This would probably require resolving
<https://commitfest.postgresql.org/patch/5885/; first.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-01-25 12:42 ` Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-04 15:54 ` Re: Make copyObject work in C++ Bryan Green <[email protected]>
0 siblings, 2 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-01-25 12:42 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Tue Jan 20, 2026 at 5:28 PM CET, Peter Eisentraut wrote:
> I have split your first patch further. For a start, I left out the
> PG_MODULE_MAGIC*-related changes and disabled the module under MSVC.
> This has been committed. I plan to let the buildfarm run with it for a
> day or two and then add in the basic MSVC support.
To hopefully make your life a bit easier. Here's a rebased version that
enables the MSVC support again, with an updated commit message.
Attachments:
[text/x-patch] v7-0001-Support-building-C-extensions-with-MSVC.patch (5.6K, 2-v7-0001-Support-building-C-extensions-with-MSVC.patch)
download | inline diff:
From 63397ed786c0feb42f9a29989f8c53fe0c9c07ec Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 2 Jan 2026 22:31:05 +0100
Subject: [PATCH v7 1/5] Support building C++ extensions with MSVC
In 476b35d4e31 a C++ test extension module was added. This test was
disabled for MSVC, because it failed to compile it in any C++ version
lower than C++20. The reason for that is our usage of designated
initializers in PG_MODULE_MAGIC_DATA (which was done in 9324c8c580).
Designated initialzers are only part of C++ from the C++20 standard
(although clang and gcc implemented support way earlier).
This reverts to using positional initializers in PG_MODULE_MAGIC_DATA so
that its possible to write C++ extensions in standard C++11. Sadly that
means that using designated initializers in C++20 is still not allowed
in PG_MODULE_MAGIC_EXT because mixing designated an positional
initializers is a C only feature. This restriction for C++ extensions is
now documented and tested.
---
doc/src/sgml/xfunc.sgml | 6 ++++++
meson.build | 4 ++++
src/include/fmgr.h | 12 +++++++-----
.../test_cplusplusext/expected/test_cplusplusext.out | 7 +++++++
src/test/modules/test_cplusplusext/meson.build | 5 -----
.../test_cplusplusext/sql/test_cplusplusext.sql | 3 +++
.../modules/test_cplusplusext/test_cplusplusext.cpp | 2 +-
7 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 70e815b8a2c..143f87a253a 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -1973,6 +1973,12 @@ PG_MODULE_MAGIC_EXT(
.name = "my_module_name",
.version = "1.2.3"
);
+</programlisting>
+
+ In C++ code, use positional arguments instead of designated initializers:
+
+<programlisting>
+PG_MODULE_MAGIC_EXT("my_module_name", "1.2.3");
</programlisting>
Subsequently the name and version can be examined via
diff --git a/meson.build b/meson.build
index df907b62da3..056412890b5 100644
--- a/meson.build
+++ b/meson.build
@@ -2238,6 +2238,10 @@ if cc.get_id() == 'msvc'
'/w24777', # 'function' : format string 'string' requires an argument of type 'type1', but variadic argument number has type 'type2' [like -Wformat]
]
+ cxxflags_warn += [
+ '/wd4200', # nonstandard extension used: zero-sized array in struct/union
+ ]
+
cppflags += [
'/DWIN32',
'/DWINDOWS',
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index eabbc78b280..1ab8749cee1 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -497,13 +497,15 @@ typedef struct
}
/*
- * Macro to fill a magic block. If any arguments are given, they should
- * be field initializers.
+ * Macro to fill a magic block. If any arguments are given, they should be
+ * field initializers. These can be designated initialzers, or non-designated
+ * initializers. If they're non-designated, they are applied after the ABI
+ * fields.
*/
#define PG_MODULE_MAGIC_DATA(...) \
{ \
- .len = sizeof(Pg_magic_struct), \
- .abi_fields = PG_MODULE_ABI_DATA, \
+ sizeof(Pg_magic_struct), \
+ PG_MODULE_ABI_DATA, \
__VA_ARGS__ \
}
@@ -524,7 +526,7 @@ extern PGDLLEXPORT const Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \
const Pg_magic_struct * \
PG_MAGIC_FUNCTION_NAME(void) \
{ \
- static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA(.name = NULL); \
+ static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA(); \
return &Pg_magic_data; \
} \
extern int no_such_variable
diff --git a/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out b/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out
index ab0b04b5c5e..25600cfd1b4 100644
--- a/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out
+++ b/src/test/modules/test_cplusplusext/expected/test_cplusplusext.out
@@ -5,3 +5,10 @@ SELECT test_cplusplus_add(1, 2);
3
(1 row)
+SELECT module_name, version FROM pg_get_loaded_modules()
+ WHERE module_name = 'test_cplusplusext';
+ module_name | version
+-------------------+---------
+ test_cplusplusext | 1.2
+(1 row)
+
diff --git a/src/test/modules/test_cplusplusext/meson.build b/src/test/modules/test_cplusplusext/meson.build
index d13210ca593..24a9cf16dca 100644
--- a/src/test/modules/test_cplusplusext/meson.build
+++ b/src/test/modules/test_cplusplusext/meson.build
@@ -4,11 +4,6 @@ if not have_cxx
subdir_done()
endif
-# Currently not supported, to be fixed.
-if cc.get_id() == 'msvc'
- subdir_done()
-endif
-
test_cplusplusext_sources = files(
'test_cplusplusext.cpp',
)
diff --git a/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql b/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql
index a41682417ae..693910ba637 100644
--- a/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql
+++ b/src/test/modules/test_cplusplusext/sql/test_cplusplusext.sql
@@ -1,3 +1,6 @@
CREATE EXTENSION test_cplusplusext;
SELECT test_cplusplus_add(1, 2);
+
+SELECT module_name, version FROM pg_get_loaded_modules()
+ WHERE module_name = 'test_cplusplusext';
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index 435937c00d2..7108e5b1cc5 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -18,7 +18,7 @@ extern "C" {
#include "postgres.h"
#include "fmgr.h"
-PG_MODULE_MAGIC;
+PG_MODULE_MAGIC_EXT("test_cplusplusext", "1.2");
PG_FUNCTION_INFO_V1(test_cplusplus_add);
}
base-commit: 9b9eaf08ab2dc22c691b22e59f1574e0f1bcc822
--
2.52.0
[text/x-patch] v7-0002-Support-using-copyObject-in-C.patch (2.9K, 3-v7-0002-Support-using-copyObject-in-C.patch)
download | inline diff:
From 2d7130aab09383c88ca8c98d666144df70d0f2da Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v7 2/5] Support using copyObject in C++
Calling copyObject in C++ without GNU extensions fails with an error
like this:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by defining pg_exprtype which maps to
typeof or decltype depending on the compiler. While pg_typeof would have
been a more natural name, that name is already taken in our codebase as
the implementation of the pg_typeof UDF.
---
src/include/c.h | 13 +++++++++++++
src/include/nodes/nodes.h | 4 ++--
.../modules/test_cplusplusext/test_cplusplusext.cpp | 6 ++++++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index c0be07a4566..08490641906 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -412,6 +412,19 @@
#define unlikely(x) ((x) != 0)
#endif
+/*
+ * pg_exprtype
+ * Get the type of an expression at compile time.
+ *
+ * In C++ we use decltype since typeof is not standard C++, while in C we use
+ * typeof when available.
+ */
+#if defined(__cplusplus)
+#define pg_exprtype(x) decltype(x)
+#elif defined(HAVE_TYPEOF)
+#define pg_exprtype(x) typeof(x)
+#endif
+
/*
* CppAsString
* Convert the argument to a string, using the C preprocessor.
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index b6ad28618ab..f5e17e670b7 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef pg_exprtype
+#define copyObject(obj) ((pg_exprtype(obj)) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index 7108e5b1cc5..48741f27949 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -17,6 +17,7 @@
extern "C" {
#include "postgres.h"
#include "fmgr.h"
+#include "nodes/parsenodes.h"
PG_MODULE_MAGIC_EXT("test_cplusplusext", "1.2");
@@ -32,6 +33,11 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
{
int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
+ RangeTblRef *node = makeNode(RangeTblRef);
+ RangeTblRef *copy = copyObject(node);
+
+ pfree(copy);
+ pfree(node);
PG_RETURN_INT32(a + b);
}
--
2.52.0
[text/x-patch] v7-0003-Use-pg_exprtype-instead-of-typeof.patch (3.1K, 4-v7-0003-Use-pg_exprtype-instead-of-typeof.patch)
download | inline diff:
From 4e7cf0efe82b5f73048c488ffb1fc6619d6dbb65 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 8 Dec 2025 08:13:51 +0100
Subject: [PATCH v7 3/5] Use pg_exprtype instead of typeof
The previous commit introduced pg_exprtype. This starts using that in a
few more places.
---
src/include/c.h | 8 ++++----
src/include/utils/relptr.h | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 08490641906..9c54a67506d 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -978,10 +978,10 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
*/
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
#define AssertVariableIsOfType(varname, typename) \
- StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ StaticAssertStmt(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename))
#define AssertVariableIsOfTypeMacro(varname, typename) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename)))
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
#define AssertVariableIsOfType(varname, typename) \
@@ -1229,11 +1229,11 @@ typedef struct PGAlignedXLogBlock
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), const underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), volatile underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#else
diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
index aeb17fa24a5..3e03d34d9ad 100644
--- a/src/include/utils/relptr.h
+++ b/src/include/utils/relptr.h
@@ -38,10 +38,10 @@
#define relptr_declare(type, relptrtype) \
typedef relptr(type) relptrtype
-#ifdef HAVE_TYPEOF
+#ifdef pg_exprtype
#define relptr_access(base, rp) \
(AssertVariableIsOfTypeMacro(base, char *), \
- (typeof((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
+ (pg_exprtype((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
(base) + (rp).relptr_off - 1))
#else
#define relptr_access(base, rp) \
@@ -68,10 +68,10 @@ relptr_store_eval(char *base, char *val)
}
}
-#ifdef HAVE_TYPEOF
+#ifdef pg_exprtype
#define relptr_store(base, rp, val) \
(AssertVariableIsOfTypeMacro(base, char *), \
- AssertVariableIsOfTypeMacro(val, typeof((rp).relptr_type)), \
+ AssertVariableIsOfTypeMacro(val, pg_exprtype((rp).relptr_type)), \
(rp).relptr_off = relptr_store_eval((base), (char *) (val)))
#else
#define relptr_store(base, rp, val) \
--
2.52.0
[text/x-patch] v7-0004-Support-using-StaticAssert-macros-in-C.patch (2.5K, 5-v7-0004-Support-using-StaticAssert-macros-in-C.patch)
download | inline diff:
From bd3384dd449d68818573599201f66e7f7048174e Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Sat, 17 Jan 2026 14:51:36 +0100
Subject: [PATCH v7 4/5] Support using StaticAssert macros in C++
StaticAssertExpr didn't work in MSVC C++. This adds a dedicated C++
definition which uses an inline lamdbda, that calls only the static
assert. Since this results in empty lambda, the actual call will be
removed by any compiler that does some optimization.
---
src/include/c.h | 8 ++++++--
src/test/modules/test_cplusplusext/test_cplusplusext.cpp | 5 +++++
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 9c54a67506d..0e4befb9e85 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -956,13 +956,17 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
static_assert(condition, errmessage)
#define StaticAssertStmt(condition, errmessage) \
do { static_assert(condition, errmessage); } while(0)
-#ifdef HAVE_STATEMENT_EXPRESSIONS
+#ifdef __cplusplus
+/* C++11 lambdas provide a convenient way to use static_assert as an expression */
+#define StaticAssertExpr(condition, errmessage) \
+ ((void) ([](){ static_assert(condition, errmessage); }(), 0))
+#elif defined(HAVE_STATEMENT_EXPRESSIONS)
#define StaticAssertExpr(condition, errmessage) \
((void) ({ static_assert(condition, errmessage); true; }))
#else
#define StaticAssertExpr(condition, errmessage) \
((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; }))
-#endif /* HAVE_STATEMENT_EXPRESSIONS */
+#endif
/*
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index 48741f27949..bb9c310504e 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -24,6 +24,8 @@ PG_MODULE_MAGIC_EXT("test_cplusplusext", "1.2");
PG_FUNCTION_INFO_V1(test_cplusplus_add);
}
+StaticAssertDecl(sizeof(int32) == 4, "int32 should be 4 bytes");
+
/*
* Simple function that returns the sum of two integers. This verifies that
* C++ extension modules can be loaded and called correctly at runtime.
@@ -36,6 +38,9 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
RangeTblRef *node = makeNode(RangeTblRef);
RangeTblRef *copy = copyObject(node);
+ StaticAssertStmt(sizeof(int32) == 4, "int32 should be 4 bytes");
+ (void) StaticAssertExpr(sizeof(int64) == 8, "int64 should be 8 bytes");
+
pfree(copy);
pfree(node);
--
2.52.0
[text/x-patch] v7-0005-Support-using-list_make-macros-in-C.patch (2.9K, 6-v7-0005-Support-using-list_make-macros-in-C.patch)
download | inline diff:
From dabaf5ef094b06a694f956f7b6749ade11c9b846 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Sat, 17 Jan 2026 14:55:28 +0100
Subject: [PATCH v7 5/5] Support using list_make macros in C++
The list_make_xxx_cell macros were using designated initializers and
these are only officially available in C++20. GCC and Clang allow them
in earlier C++ versions too, but MSVC is strict about it. Since we want
to support C++11 this changes these macros to use inline functions
instead, which work across both C and C++.
---
src/include/nodes/pg_list.h | 43 ++++++++++++++++---
.../test_cplusplusext/test_cplusplusext.cpp | 14 ++++++
2 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index ae80975548f..ba43d36bc89 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -202,12 +202,45 @@ list_length(const List *l)
#define llast_node(type,l) castNode(type, llast(l))
/*
- * Convenience macros for building fixed-length lists
+ * Convenience functions for building fixed-length lists. These cannot be
+ * macros with designated initializers, because we want these functions to be
+ * usable from C++ versions below C++20.
*/
-#define list_make_ptr_cell(v) ((ListCell) {.ptr_value = (v)})
-#define list_make_int_cell(v) ((ListCell) {.int_value = (v)})
-#define list_make_oid_cell(v) ((ListCell) {.oid_value = (v)})
-#define list_make_xid_cell(v) ((ListCell) {.xid_value = (v)})
+static inline ListCell
+list_make_ptr_cell(void *v)
+{
+ ListCell c;
+
+ c.ptr_value = v;
+ return c;
+}
+
+static inline ListCell
+list_make_int_cell(int v)
+{
+ ListCell c;
+
+ c.int_value = v;
+ return c;
+}
+
+static inline ListCell
+list_make_oid_cell(Oid v)
+{
+ ListCell c;
+
+ c.oid_value = v;
+ return c;
+}
+
+static inline ListCell
+list_make_xid_cell(TransactionId v)
+{
+ ListCell c;
+
+ c.xid_value = v;
+ return c;
+}
#define list_make1(x1) \
list_make1_impl(T_List, list_make_ptr_cell(x1))
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index bb9c310504e..2bdf2c3d057 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -17,6 +17,7 @@
extern "C" {
#include "postgres.h"
#include "fmgr.h"
+#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
PG_MODULE_MAGIC_EXT("test_cplusplusext", "1.2");
@@ -41,6 +42,19 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
StaticAssertStmt(sizeof(int32) == 4, "int32 should be 4 bytes");
(void) StaticAssertExpr(sizeof(int64) == 8, "int64 should be 8 bytes");
+ List *list = list_make1(node);
+
+ foreach_ptr(RangeTblRef, rtr, list)
+ {
+ (void) rtr;
+ }
+
+ foreach_node(RangeTblRef, rtr, list)
+ {
+ (void) rtr;
+ }
+
+ list_free(list);
pfree(copy);
pfree(node);
--
2.52.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-01-25 16:50 ` Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Andres Freund @ 2026-01-25 16:50 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
Hi,
On 2026-01-25 13:42:51 +0100, Jelte Fennema-Nio wrote:
> This reverts to using positional initializers in PG_MODULE_MAGIC_DATA so
> that its possible to write C++ extensions in standard C++11. Sadly that
> means that using designated initializers in C++20 is still not allowed
> in PG_MODULE_MAGIC_EXT because mixing designated an positional
> initializers is a C only feature. This restriction for C++ extensions is
> now documented and tested.
I'm pretty sceptical this is the right direction. We were going for designated
initializers for a reason, namely that we expect more arguments to be added
over time and perhaps eventually also to remove some. And this will just lead
to that being harder because we have to worry about C++ extensions.
But I'm also confused as to why it's needed - there's nomixing of designated
and non-designated initializers that I can see? If you use
PG_MODULE_MAGIC_EXT(.name = "whatnot"), it evaluates down to
extern __attribute__((visibility("default"))) const Pg_magic_struct *Pg_magic_func(void); const Pg_magic_struct * Pg_magic_func(void) { static const Pg_magic_struct Pg_magic_data = { .len = sizeof(Pg_magic_struct), .abi_fields = { 190000 / 100, 100, 32, 64, true, "PostgreSQL", }, .name="whatnot"}; return &Pg_magic_data; } extern int no_such_variable;
And indeed, contra to what you reported upthread, I can't get clang to report
a warning about that. I do obviously see warnings about the wrong order if I
pass the arguments in the wrong order, but that's a lot less problematic. And
omitted args don't trigger warnings, as you noted.
Greetings,
Andres Freund
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
@ 2026-01-25 17:52 ` Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-26 10:29 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 2 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-01-25 17:52 UTC (permalink / raw)
To: Andres Freund <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Sun Jan 25, 2026 at 5:50 PM CET, Andres Freund wrote:
> I'm pretty sceptical this is the right direction.
The only other option I can think of is not supporting C++ extension on
MSVC unless they are compiled with C++20 (or later). I don't
particularly care about Windows C++ extensions myself, so I personally
would be fine with that choice. It seems a bit harsh, though.
> We were going for designated
> initializers for a reason, namely that we expect more arguments to be added
> over time and perhaps eventually also to remove some. And this will just lead
> to that being harder because we have to worry about C++ extensions.
Adding new arguments (aka fields) should cause no problems. Assuming
we'd add them at the end of the Pg_magic_struct definition. Removing
ones seems like even for C you'd need different PG_MODULE_MAGIC_EXT
invocations depending on PG_VERSION_NUM. I don't see how using
positional args would make that harder.
> But I'm also confused as to why it's needed - there's nomixing of designated
> and non-designated initializers that I can see? If you use
> PG_MODULE_MAGIC_EXT(.name = "whatnot"), it evaluates down to
>
> extern __attribute__((visibility("default"))) const Pg_magic_struct *Pg_magic_func(void); const Pg_magic_struct * Pg_magic_func(void) { static const Pg_magic_struct Pg_magic_data = { .len = sizeof(Pg_magic_struct), .abi_fields = { 190000 / 100, 100, 32, 64, true, "PostgreSQL", }, .name="whatnot"}; return &Pg_magic_data; } extern int no_such_variable;
>
> And indeed, contra to what you reported upthread, I can't get clang to report
> a warning about that. I do obviously see warnings about the wrong order if I
> pass the arguments in the wrong order, but that's a lot less problematic. And
> omitted args don't trigger warnings, as you noted.
It sounds like I wasn't clear enough what the problem was. The main
problem currently is that MSVC C++ fails to compile a cpp file
containing PG_MODULE_MAGIC (or PG_MODULE_MAGIC_EXT) unless you use /std:c++20.
Afaict it would have been possible to do so before 9324c8c580 (aka
anything before PG18), but since that commit you need /std:c++20. The
fact that we haven't heard anyone complain so far, might be an indication
that not many people (or maybe anyone) is using C++ extensions on Windows.
The only way to make PG_MODULE_MAGIC work on MSVC pre-C++20 is to
partially revert 9324c8c580, and use positional arguments in the
definition of PG_MODULE_MAGIC_DATA again. Like I've done in v7-0001.
For C extensions v7-0001 has no downsides. However, after applying
v7-0001, C++ extensions that use PG_MODULE_MAGIC_EXT with designated
parameters will get the following warning on at least clang 18 on my
machine:
meson setup --prefix ~/.pgenv/pgsql-master --debug build --reconfigure -Dc_args='-fno-omit-frame-pointer' -Dcassert=true
meson test -C build --suite setup --suite test_cplusplusext
[2202/2268] Compiling C++ object src/test/modules/test_cplusplusext/test_cplusplusext.so.p/test_cplusplusext.cpp.o
../src/test/modules/test_cplusplusext/test_cplusplusext.cpp:23:21: warning: mixture of designated and non-designated initializers in the same initializer list is a C99 extension [-Wc99-designator]
23 | PG_MODULE_MAGIC_EXT(.name="test_cplusplusext",.version= "1.2");
| ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/include/fmgr.h:548:24: note: expanded from macro 'PG_MODULE_MAGIC_EXT'
548 | PG_MODULE_MAGIC_DATA(__VA_ARGS__); \
| ^~~~~~~~~~~
../src/include/fmgr.h:509:2: note: expanded from macro 'PG_MODULE_MAGIC_DATA'
509 | __VA_ARGS__ \
| ^~~~~~~~~~~
../src/test/modules/test_cplusplusext/test_cplusplusext.cpp:23:1: note: first non-designated initializer is here
23 | PG_MODULE_MAGIC_EXT(.name="test_cplusplusext",.version= "1.2");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/include/fmgr.h:548:3: note: expanded from macro 'PG_MODULE_MAGIC_EXT'
548 | PG_MODULE_MAGIC_DATA(__VA_ARGS__); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/include/fmgr.h:507:2: note: expanded from macro 'PG_MODULE_MAGIC_DATA'
507 | sizeof(Pg_magic_struct), \
| ^~~~~~~~~~~~~~~~~~~~~~~
Note that you need to use meson test, not meson install, otherwise
test_cplusplusext.cpp won't get compiled.
So to be clear, yes right now there's no mixing of designated and
non-designated initializers. But after applying v7-0001 there would be
when you use something like this:
PG_MODULE_MAGIC_EXT(.name="test_cplusplusext",.version= "1.2");
And while the C standard allows mixing designated and non-designated
initializerss, the C++ standard (even C++20) does not.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-01-25 20:06 ` Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Andres Freund @ 2026-01-25 20:06 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
Hi,
On 2026-01-25 18:52:37 +0100, Jelte Fennema-Nio wrote:
> On Sun Jan 25, 2026 at 5:50 PM CET, Andres Freund wrote:
> > We were going for designated
> > initializers for a reason, namely that we expect more arguments to be added
> > over time and perhaps eventually also to remove some. And this will just lead
> > to that being harder because we have to worry about C++ extensions.
>
> Adding new arguments (aka fields) should cause no problems. Assuming
> we'd add them at the end of the Pg_magic_struct definition. Removing
> ones seems like even for C you'd need different PG_MODULE_MAGIC_EXT
> invocations depending on PG_VERSION_NUM. I don't see how using
> positional args would make that harder.
Named args make that easier in two ways: First, only extensions using the
to-be-removed option will fail. Second, removal of options reliably generates
errors, rather than bogusly use one field for another, just because the types
are compatible.
Greetings,
Andres Freund
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
@ 2026-02-13 10:28 ` Jelte Fennema-Nio <[email protected]>
2026-02-17 09:24 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
0 siblings, 3 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-02-13 10:28 UTC (permalink / raw)
To: Andres Freund <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Sun Jan 25, 2026 at 9:06 PM CET, Andres Freund wrote:
> Named args make that easier in two ways: First, only extensions using the
> to-be-removed option will fail. Second, removal of options reliably generates
> errors, rather than bogusly use one field for another, just because the types
> are compatible.
After discussing the topic in-person with Peter at FOSDEM. We agreed
that the best road forward was to not bother with MSVC for now. No-one
has actually expressed an interest in being able to build C++ extension
using MSVC, and the effort to support it is both non-trivial and not
without downsides to the rest of the codebase. We can always come back
to this later, possibly requiring C++20 on MSVC.
So I've removed that patch and now this patchset its goal is to improve
compatibiltity with the C++ flavor of GCC and Clang.
Patch 1 and 2 add some more macro calls to our test C++ extension. These
macros already work in GCC and Clang, this is purely to test for future
regressinos.
Patch 3 makes copyObject work when using GCC or Clang with -std=c++11 by
introducing pg_exprtype.
Patch 4 starts using pg_exprtype in more places.
I'm also working on some patches to support
StaticAssertVariableIsOfType, but I've run into some ICE compiler errors
of MSVC 2019.
Attachments:
[text/x-patch] v8-0001-Test-List-macros-in-C-extensions.patch (1.6K, 2-v8-0001-Test-List-macros-in-C-extensions.patch)
download | inline diff:
From 8a5bbbd0e73edafc340c938ec6e234384dbe672a Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 13 Feb 2026 09:14:47 +0100
Subject: [PATCH v8 1/6] Test List macros in C++ extensions
All of these macros already work in C++ with Clang and GCC (the only
compilers we're currently testing C++ extension support for). This adds
a regression test for them in our test C++ extension, so we can safely
change their implementation without accidentally breaking C++. Some of
the List macros didn't work in C++ in the past (d5ca15ee5), this would
have caught that.
---
.../test_cplusplusext/test_cplusplusext.cpp | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index 435937c00d2..f1a2ab7f2bf 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -17,6 +17,8 @@
extern "C" {
#include "postgres.h"
#include "fmgr.h"
+#include "nodes/pg_list.h"
+#include "nodes/primnodes.h"
PG_MODULE_MAGIC;
@@ -32,6 +34,21 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
{
int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
+ RangeTblRef *node = makeNode(RangeTblRef);
+ List *list = list_make1(node);
+
+ foreach_ptr(RangeTblRef, rtr, list)
+ {
+ (void) rtr;
+ }
+
+ foreach_node(RangeTblRef, rtr, list)
+ {
+ (void) rtr;
+ }
+
+ list_free(list);
+ pfree(node);
PG_RETURN_INT32(a + b);
}
base-commit: d7edcec35c7c28edb3bf283dfe9c892b042ca158
--
2.52.0
[text/x-patch] v8-0002-Test-most-StaticAssert-macros-in-C-extensions.patch (1.6K, 3-v8-0002-Test-most-StaticAssert-macros-in-C-extensions.patch)
download | inline diff:
From 8f9d2a63bcdf30a445cb24c5453f34d8f54a4b29 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Sat, 17 Jan 2026 14:51:36 +0100
Subject: [PATCH v8 2/6] Test most StaticAssert macros in C++ extensions
Most of the StaticAssert macros already worked in C++ with Clang and GCC
(the only compilers we're currently testing C++ extension support for).
This adds a regression test for them in our test C++ extension, so we
can safely change their implementation without accidentally breaking
C++.
The only macros that StaticAssert macros that don't work yet are the
StaticAssertVariableIsOfType and StaticAssertVariableIsOfTypeMacro.
These will be added in a follow on commit.
---
src/test/modules/test_cplusplusext/test_cplusplusext.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index f1a2ab7f2bf..8c2eabcca43 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -25,6 +25,8 @@ PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(test_cplusplus_add);
}
+StaticAssertDecl(sizeof(int32) == 4, "int32 should be 4 bytes");
+
/*
* Simple function that returns the sum of two integers. This verifies that
* C++ extension modules can be loaded and called correctly at runtime.
@@ -47,6 +49,9 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
(void) rtr;
}
+ StaticAssertStmt(sizeof(int32) == 4, "int32 should be 4 bytes");
+ (void) StaticAssertExpr(sizeof(int64) == 8, "int64 should be 8 bytes");
+
list_free(list);
pfree(node);
--
2.52.0
[text/x-patch] v8-0003-Support-using-copyObject-in-C.patch (2.9K, 4-v8-0003-Support-using-copyObject-in-C.patch)
download | inline diff:
From cb57b403ee7819f7512a5e5edcd4ce1cb876ee46 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v8 3/6] Support using copyObject in C++
Calling copyObject in C++ without GNU extensions (e.g. then using
-std=c++11 instead of -std=gnu++11) fails with an error like this:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by defining pg_exprtype which maps to
typeof or decltype depending on whether it's a C or C++ compiler. While
pg_typeof would have been a more natural name, that name is already
taken in our codebase as the implementation of the pg_typeof UDF.
---
src/include/c.h | 13 +++++++++++++
src/include/nodes/nodes.h | 4 ++--
.../modules/test_cplusplusext/test_cplusplusext.cpp | 2 ++
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 3fc09ec1e4a..9f418e432ea 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -412,6 +412,19 @@
#define unlikely(x) ((x) != 0)
#endif
+/*
+ * pg_exprtype
+ * Get the type of an expression at compile time.
+ *
+ * In C++ we use decltype since typeof is not standard C++, while in C we use
+ * typeof when available.
+ */
+#if defined(__cplusplus)
+#define pg_exprtype(x) decltype(x)
+#elif defined(HAVE_TYPEOF)
+#define pg_exprtype(x) typeof(x)
+#endif
+
/*
* CppAsString
* Convert the argument to a string, using the C preprocessor.
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 59a7df31aba..a03c85f1b01 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef pg_exprtype
+#define copyObject(obj) ((pg_exprtype(obj)) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index 8c2eabcca43..5e6c8f85f6f 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -37,6 +37,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
RangeTblRef *node = makeNode(RangeTblRef);
+ RangeTblRef *copy = copyObject(node);
List *list = list_make1(node);
foreach_ptr(RangeTblRef, rtr, list)
@@ -54,6 +55,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
list_free(list);
pfree(node);
+ pfree(copy);
PG_RETURN_INT32(a + b);
}
--
2.52.0
[text/x-patch] v8-0004-Use-pg_exprtype-instead-of-typeof.patch (3.2K, 5-v8-0004-Use-pg_exprtype-instead-of-typeof.patch)
download | inline diff:
From d2986a90548f5dce7fbd6d0e09d7d881f15e3e53 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 8 Dec 2025 08:13:51 +0100
Subject: [PATCH v8 4/6] Use pg_exprtype instead of typeof
The previous commit introduced pg_exprtype. This starts using that in a
few more places.
---
src/include/c.h | 8 ++++----
src/include/utils/relptr.h | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 9f418e432ea..b448a4a8775 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -978,10 +978,10 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
*/
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
#define StaticAssertVariableIsOfType(varname, typename) \
- StaticAssertDecl(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ StaticAssertDecl(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename))
#define StaticAssertVariableIsOfTypeMacro(varname, typename) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename)))
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
#define StaticAssertVariableIsOfType(varname, typename) \
@@ -1245,11 +1245,11 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), const underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(pg_exprtype(expr), volatile underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#else
diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
index 94975f2f237..2df6c673017 100644
--- a/src/include/utils/relptr.h
+++ b/src/include/utils/relptr.h
@@ -38,10 +38,10 @@
#define relptr_declare(type, relptrtype) \
typedef relptr(type) relptrtype
-#ifdef HAVE_TYPEOF
+#ifdef pg_exprtype
#define relptr_access(base, rp) \
(StaticAssertVariableIsOfTypeMacro(base, char *), \
- (typeof((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
+ (pg_exprtype((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
(base) + (rp).relptr_off - 1))
#else
#define relptr_access(base, rp) \
@@ -68,10 +68,10 @@ relptr_store_eval(char *base, char *val)
}
}
-#ifdef HAVE_TYPEOF
+#ifdef pg_exprtype
#define relptr_store(base, rp, val) \
(StaticAssertVariableIsOfTypeMacro(base, char *), \
- StaticAssertVariableIsOfTypeMacro(val, typeof((rp).relptr_type)), \
+ StaticAssertVariableIsOfTypeMacro(val, pg_exprtype((rp).relptr_type)), \
(rp).relptr_off = relptr_store_eval((base), (char *) (val)))
#else
#define relptr_store(base, rp, val) \
--
2.52.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-02-17 09:24 ` Peter Eisentraut <[email protected]>
2 siblings, 0 replies; 39+ messages in thread
From: Peter Eisentraut @ 2026-02-17 09:24 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On 13.02.26 11:28, Jelte Fennema-Nio wrote:
> On Sun Jan 25, 2026 at 9:06 PM CET, Andres Freund wrote:
>> Named args make that easier in two ways: First, only extensions using the
>> to-be-removed option will fail. Second, removal of options reliably
>> generates
>> errors, rather than bogusly use one field for another, just because
>> the types
>> are compatible.
>
> After discussing the topic in-person with Peter at FOSDEM. We agreed
> that the best road forward was to not bother with MSVC for now. No-one
> has actually expressed an interest in being able to build C++ extension
> using MSVC, and the effort to support it is both non-trivial and not
> without downsides to the rest of the codebase. We can always come back
> to this later, possibly requiring C++20 on MSVC.
>
> So I've removed that patch and now this patchset its goal is to improve
> compatibiltity with the C++ flavor of GCC and Clang.
>
> Patch 1 and 2 add some more macro calls to our test C++ extension. These
> macros already work in GCC and Clang, this is purely to test for future
> regressinos.
I have committed these two. I'll give them some time on the buildfarm
and then look at the rest.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-02-19 08:31 ` Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-02-19 08:31 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 13.02.26 11:28, Jelte Fennema-Nio wrote:
> Patch 3 makes copyObject work when using GCC or Clang with -std=c++11 by
> introducing pg_exprtype.
>
> Patch 4 starts using pg_exprtype in more places.
I found this paper
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm
which led to the addition of typeof into the C standard.
It contains a section 'Why not "decltype"?' that explains how decltype
is different, but it also explains that if typeof were added to C++,
then it would be
std::remove_reference_t<decltype(T)>
What I suggest we should do here is:
1. Add a configure test that checks if the C++ compiler supports typeof.
2. If not, #define typeof to the above expression.
Then code can continue to use typeof unchanged.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-02-20 09:47 ` Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-02-20 09:47 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Thu Feb 19, 2026 at 9:31 AM CET, Peter Eisentraut wrote:
> What I suggest we should do here is:
>
> 1. Add a configure test that checks if the C++ compiler supports typeof.
>
> 2. If not, #define typeof to the above expression.
>
> Then code can continue to use typeof unchanged.
Makes total sense, I didn't realise decltype and typeof were not quite
the same thing. Attached is an updated patchset that does that.
It also includes a patch that improves unconstify and unvolatize by
using StaticAssertVariableIsOfTypeMacro instead of a custom version of
that assertion. (Like I said, in a future patch I intend to make
StaticAssertVariableIsOfTypeMacro work in C++ as well, but this seemed
like a good improvement anyway)
Attachments:
[text/x-patch] v9-0001-Support-using-copyObject-in-C.patch (7.7K, 2-v9-0001-Support-using-copyObject-in-C.patch)
download | inline diff:
From 1ff9279f3acb207e23e8b20b23429283b81a94fb Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v9 1/3] Support using copyObject in C++
Calling copyObject in C++ without GNU extensions (e.g. then using
-std=c++11 instead of -std=gnu++11) fails with an error like this:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler used to compile postgres supporting
typeof, but that function actually not being present in the C++
compiler. This fixes that by explicitely checking for typeof support in
C++ and then either use that, or define typeof ourselves as:
std::remove_reference_t<decltype(x)>
According to the paper that led to adding typeof to the C standard,
that's the C++ equivalent of the C typeof:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
---
config/c-compiler.m4 | 29 ++++++++++
configure | 54 +++++++++++++++++++
configure.ac | 1 +
meson.build | 25 +++++++++
src/include/c.h | 21 ++++++++
src/include/pg_config.h.in | 4 ++
.../test_cplusplusext/test_cplusplusext.cpp | 2 +
7 files changed, 136 insertions(+)
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 1509dbfa2ab..5b3cbc7e8e8 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -193,6 +193,35 @@ fi])# PGAC_C_TYPEOF
+# PGAC_CXX_TYPEOF
+# ----------------
+# Check if the C++ compiler understands typeof or a variant. Define
+# HAVE_CXX_TYPEOF if so, and define 'pg_cxx_typeof' to the actual key word.
+#
+AC_DEFUN([PGAC_CXX_TYPEOF],
+[AC_CACHE_CHECK(for C++ typeof, pgac_cv_cxx_typeof,
+[pgac_cv_cxx_typeof=no
+AC_LANG_PUSH(C++)
+for pgac_kw in typeof __typeof__; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;])],
+[pgac_cv_cxx_typeof=$pgac_kw])
+ test "$pgac_cv_cxx_typeof" != no && break
+done
+AC_LANG_POP([])])
+if test "$pgac_cv_cxx_typeof" != no; then
+ AC_DEFINE(HAVE_CXX_TYPEOF, 1,
+ [Define to 1 if your C++ compiler understands `typeof' or something similar.])
+ if test "$pgac_cv_cxx_typeof" != typeof; then
+ AC_DEFINE_UNQUOTED(pg_cxx_typeof, $pgac_cv_cxx_typeof, [Define to how the C++ compiler spells `typeof'.])
+ fi
+fi])# PGAC_CXX_TYPEOF
+
+
+
# PGAC_C_TYPES_COMPATIBLE
# -----------------------
# Check if the C compiler understands __builtin_types_compatible_p,
diff --git a/configure b/configure
index e1a08129974..3995a16fd1c 100755
--- a/configure
+++ b/configure
@@ -14968,6 +14968,60 @@ _ACEOF
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ typeof" >&5
+$as_echo_n "checking for C++ typeof... " >&6; }
+if ${pgac_cv_cxx_typeof+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ pgac_cv_cxx_typeof=no
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+for pgac_kw in typeof __typeof__; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ pgac_cv_cxx_typeof=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$pgac_cv_cxx_typeof" != no && break
+done
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_cxx_typeof" >&5
+$as_echo "$pgac_cv_cxx_typeof" >&6; }
+if test "$pgac_cv_cxx_typeof" != no; then
+
+$as_echo "#define HAVE_CXX_TYPEOF 1" >>confdefs.h
+
+ if test "$pgac_cv_cxx_typeof" != typeof; then
+
+cat >>confdefs.h <<_ACEOF
+#define pg_cxx_typeof $pgac_cv_cxx_typeof
+_ACEOF
+
+ fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
if ${pgac_cv__types_compatible+:} false; then :
diff --git a/configure.ac b/configure.ac
index cc85c233c03..754dc50d6ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1716,6 +1716,7 @@ PGAC_PRINTF_ARCHETYPE
PGAC_CXX_PRINTF_ARCHETYPE
PGAC_C_STATEMENT_EXPRESSIONS
PGAC_C_TYPEOF
+PGAC_CXX_TYPEOF
PGAC_C_TYPES_COMPATIBLE
PGAC_C_BUILTIN_CONSTANT_P
PGAC_C_BUILTIN_OP_OVERFLOW
diff --git a/meson.build b/meson.build
index 055e96315d0..06ab917365e 100644
--- a/meson.build
+++ b/meson.build
@@ -2882,6 +2882,31 @@ int main(void)
endif
endforeach
+# Check if the C++ compiler understands typeof or a variant.
+if have_cxx
+ foreach kw : ['typeof', '__typeof__']
+ if cxx.compiles('''
+int main(void)
+{
+ int x = 0;
+ @0@(x) y;
+ y = x;
+ return y;
+}
+'''.format(kw),
+ name: 'C++ ' + kw,
+ args: test_c_args, include_directories: postgres_inc)
+
+ cdata.set('HAVE_CXX_TYPEOF', 1)
+ if kw != 'typeof'
+ cdata.set('pg_cxx_typeof', kw)
+ endif
+
+ break
+ endif
+ endforeach
+endif
+
# MSVC doesn't cope well with defining restrict to __restrict, the
# spelling it understands, because it conflicts with
diff --git a/src/include/c.h b/src/include/c.h
index 7ee4751992f..c3b3e9eea4e 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -424,6 +424,27 @@
#define unlikely(x) ((x) != 0)
#endif
+/*
+ * Provide typeof in C++ for C++ compilers that don't support typeof natively.
+ * It might be spelled __typeof__ instead of typeof, in which case
+ * pg_cxx_typeof provides that mapping. If neither is supported, we can use
+ * decltype, but to make it equivalent to C's typeof, we need to remove
+ * references from the result [1]. Also ensure HAVE_TYPEOF is set so that
+ * typeof-dependent code is always enabled in C++ mode.
+ *
+ * [1]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
+ */
+#if defined(__cplusplus)
+#ifdef pg_cxx_typeof
+#define typeof(x) pg_cxx_typeof(x)
+#elif !defined(HAVE_CXX_TYPEOF)
+#define typeof(x) std::remove_reference_t<decltype(x)>
+#endif
+#ifndef HAVE_TYPEOF
+#define HAVE_TYPEOF 1
+#endif
+#endif
+
/*
* CppAsString
* Convert the argument to a string, using the C preprocessor.
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 3824a5571bb..0059408569d 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -454,6 +454,10 @@
/* Define to 1 if your compiler understands `typeof' or something similar. */
#undef HAVE_TYPEOF
+/* Define to 1 if your C++ compiler understands `typeof' or something similar.
+ */
+#undef HAVE_CXX_TYPEOF
+
/* Define to 1 if you have the <uchar.h> header file. */
#undef HAVE_UCHAR_H
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index 8c2eabcca43..5e6c8f85f6f 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -37,6 +37,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
RangeTblRef *node = makeNode(RangeTblRef);
+ RangeTblRef *copy = copyObject(node);
List *list = list_make1(node);
foreach_ptr(RangeTblRef, rtr, list)
@@ -54,6 +55,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
list_free(list);
pfree(node);
+ pfree(copy);
PG_RETURN_INT32(a + b);
}
base-commit: ba401828c194c17031a6a2dedd97bc0defd80d4b
--
2.53.0
[text/x-patch] v9-0002-Use-typeof-everywhere-instead-of-compiler-specifi.patch (2.3K, 3-v9-0002-Use-typeof-everywhere-instead-of-compiler-specifi.patch)
download | inline diff:
From c0537483fbdace6967df3aa1b76f1db6c66a5883 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 8 Dec 2025 08:13:51 +0100
Subject: [PATCH v9 2/3] Use typeof everywhere instead of compiler specific
spellings
We define typeof ourselves as __typeof__ if it does not exist. So let's
actually use that for consistency. The meson/autoconf checks for
__builtin_types_compatible_p still use __typeof__ though, because there
we have not redefined it.
---
src/include/c.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index c3b3e9eea4e..07e931a6c89 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1008,10 +1008,10 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
*/
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
#define StaticAssertVariableIsOfType(varname, typename) \
- StaticAssertDecl(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ StaticAssertDecl(__builtin_types_compatible_p(typeof(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename))
#define StaticAssertVariableIsOfTypeMacro(varname, typename) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ (StaticAssertExpr(__builtin_types_compatible_p(typeof(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename)))
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
#define StaticAssertVariableIsOfType(varname, typename) \
@@ -1275,11 +1275,11 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), const underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), volatile underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#else
--
2.53.0
[text/x-patch] v9-0003-Make-unconstify-and-unvolatize-use-StaticAssertVa.patch (1.7K, 4-v9-0003-Make-unconstify-and-unvolatize-use-StaticAssertVa.patch)
download | inline diff:
From 37021f7b2cae580ca348c8600f9644f928b48232 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Thu, 19 Feb 2026 23:55:43 +0100
Subject: [PATCH v9 3/3] Make unconstify and unvolatize use
StaticAssertVariableIsOfTypeMacro
The unconstify and unvolatize macros had an almost identical assertion
as was already defined in StaticAssertVariableIsOfTypeMacro, only it had
a less useful error message and didn't have a sizeof fallback.
---
src/include/c.h | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 07e931a6c89..5fa366914d8 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1273,20 +1273,13 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
#if defined(__cplusplus)
#define unconstify(underlying_type, expr) const_cast<underlying_type>(expr)
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
-#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
+#else
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), const underlying_type), \
- "wrong cast"), \
+ (StaticAssertVariableIsOfTypeMacro(expr, const underlying_type), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), volatile underlying_type), \
- "wrong cast"), \
+ (StaticAssertVariableIsOfTypeMacro(expr, volatile underlying_type), \
(underlying_type) (expr))
-#else
-#define unconstify(underlying_type, expr) \
- ((underlying_type) (expr))
-#define unvolatize(underlying_type, expr) \
- ((underlying_type) (expr))
#endif
/*
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-02-27 16:40 ` Jelte Fennema-Nio <[email protected]>
2026-02-27 16:52 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-02 10:56 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 2 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-02-27 16:40 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Fri Feb 20, 2026 at 10:47 AM CET, Jelte Fennema-Nio wrote:
> Makes total sense, I didn't realise decltype and typeof were not quite
> the same thing. Attached is an updated patchset that does that.
Same patchset as before, but now also including a C++ fallback for
__builtin_types_compatible_p.
Attachments:
[text/x-patch] v10-0001-Support-using-copyObject-in-C.patch (7.6K, 2-v10-0001-Support-using-copyObject-in-C.patch)
download | inline diff:
From 077bb1a951c4eb6d61ba2e977c6b09d8d295831a Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 5 Dec 2025 15:37:59 +0100
Subject: [PATCH v10 1/4] Support using copyObject in C++
Calling copyObject in C++ without GNU extensions (e.g. then using
-std=c++11 instead of -std=gnu++11) fails with an error like this:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler used to compile postgres supporting
typeof, but that function actually not being present in the C++
compiler. This fixes that by explicitely checking for typeof support in
C++ and then either use that, or define typeof ourselves as:
std::remove_reference_t<decltype(x)>
According to the paper that led to adding typeof to the C standard,
that's the C++ equivalent of the C typeof:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
---
config/c-compiler.m4 | 29 ++++++++++
configure | 54 +++++++++++++++++++
configure.ac | 1 +
meson.build | 25 +++++++++
src/include/c.h | 21 ++++++++
src/include/pg_config.h.in | 4 ++
.../test_cplusplusext/test_cplusplusext.cpp | 2 +
7 files changed, 136 insertions(+)
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 1509dbfa2ab..5b3cbc7e8e8 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -193,6 +193,35 @@ fi])# PGAC_C_TYPEOF
+# PGAC_CXX_TYPEOF
+# ----------------
+# Check if the C++ compiler understands typeof or a variant. Define
+# HAVE_CXX_TYPEOF if so, and define 'pg_cxx_typeof' to the actual key word.
+#
+AC_DEFUN([PGAC_CXX_TYPEOF],
+[AC_CACHE_CHECK(for C++ typeof, pgac_cv_cxx_typeof,
+[pgac_cv_cxx_typeof=no
+AC_LANG_PUSH(C++)
+for pgac_kw in typeof __typeof__; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;])],
+[pgac_cv_cxx_typeof=$pgac_kw])
+ test "$pgac_cv_cxx_typeof" != no && break
+done
+AC_LANG_POP([])])
+if test "$pgac_cv_cxx_typeof" != no; then
+ AC_DEFINE(HAVE_CXX_TYPEOF, 1,
+ [Define to 1 if your C++ compiler understands `typeof' or something similar.])
+ if test "$pgac_cv_cxx_typeof" != typeof; then
+ AC_DEFINE_UNQUOTED(pg_cxx_typeof, $pgac_cv_cxx_typeof, [Define to how the C++ compiler spells `typeof'.])
+ fi
+fi])# PGAC_CXX_TYPEOF
+
+
+
# PGAC_C_TYPES_COMPATIBLE
# -----------------------
# Check if the C compiler understands __builtin_types_compatible_p,
diff --git a/configure b/configure
index a285a6ec3d7..604f9e0100b 100755
--- a/configure
+++ b/configure
@@ -15078,6 +15078,60 @@ _ACEOF
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ typeof" >&5
+$as_echo_n "checking for C++ typeof... " >&6; }
+if ${pgac_cv_cxx_typeof+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ pgac_cv_cxx_typeof=no
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+for pgac_kw in typeof __typeof__; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+y = x;
+return y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ pgac_cv_cxx_typeof=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$pgac_cv_cxx_typeof" != no && break
+done
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_cxx_typeof" >&5
+$as_echo "$pgac_cv_cxx_typeof" >&6; }
+if test "$pgac_cv_cxx_typeof" != no; then
+
+$as_echo "#define HAVE_CXX_TYPEOF 1" >>confdefs.h
+
+ if test "$pgac_cv_cxx_typeof" != typeof; then
+
+cat >>confdefs.h <<_ACEOF
+#define pg_cxx_typeof $pgac_cv_cxx_typeof
+_ACEOF
+
+ fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
if ${pgac_cv__types_compatible+:} false; then :
diff --git a/configure.ac b/configure.ac
index 476a76c7991..93ecf41447b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1732,6 +1732,7 @@ PGAC_PRINTF_ARCHETYPE
PGAC_CXX_PRINTF_ARCHETYPE
PGAC_C_STATEMENT_EXPRESSIONS
PGAC_C_TYPEOF
+PGAC_CXX_TYPEOF
PGAC_C_TYPES_COMPATIBLE
PGAC_C_BUILTIN_CONSTANT_P
PGAC_C_BUILTIN_OP_OVERFLOW
diff --git a/meson.build b/meson.build
index 5122706477d..9cc95f0be5f 100644
--- a/meson.build
+++ b/meson.build
@@ -2953,6 +2953,31 @@ int main(void)
endif
endforeach
+# Check if the C++ compiler understands typeof or a variant.
+if have_cxx
+ foreach kw : ['typeof', '__typeof__']
+ if cxx.compiles('''
+int main(void)
+{
+ int x = 0;
+ @0@(x) y;
+ y = x;
+ return y;
+}
+'''.format(kw),
+ name: 'C++ ' + kw,
+ args: test_c_args, include_directories: postgres_inc)
+
+ cdata.set('HAVE_CXX_TYPEOF', 1)
+ if kw != 'typeof'
+ cdata.set('pg_cxx_typeof', kw)
+ endif
+
+ break
+ endif
+ endforeach
+endif
+
# MSVC doesn't cope well with defining restrict to __restrict, the
# spelling it understands, because it conflicts with
diff --git a/src/include/c.h b/src/include/c.h
index fb0ea1bc680..a4fee84398d 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -424,6 +424,27 @@
#define unlikely(x) ((x) != 0)
#endif
+/*
+ * Provide typeof in C++ for C++ compilers that don't support typeof natively.
+ * It might be spelled __typeof__ instead of typeof, in which case
+ * pg_cxx_typeof provides that mapping. If neither is supported, we can use
+ * decltype, but to make it equivalent to C's typeof, we need to remove
+ * references from the result [1]. Also ensure HAVE_TYPEOF is set so that
+ * typeof-dependent code is always enabled in C++ mode.
+ *
+ * [1]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
+ */
+#if defined(__cplusplus)
+#ifdef pg_cxx_typeof
+#define typeof(x) pg_cxx_typeof(x)
+#elif !defined(HAVE_CXX_TYPEOF)
+#define typeof(x) std::remove_reference_t<decltype(x)>
+#endif
+#ifndef HAVE_TYPEOF
+#define HAVE_TYPEOF 1
+#endif
+#endif
+
/*
* CppAsString
* Convert the argument to a string, using the C preprocessor.
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index a0bd84376e7..a970577ae3e 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -451,6 +451,10 @@
/* Define to 1 if your compiler understands `typeof' or something similar. */
#undef HAVE_TYPEOF
+/* Define to 1 if your C++ compiler understands `typeof' or something similar.
+ */
+#undef HAVE_CXX_TYPEOF
+
/* Define to 1 if you have the <uchar.h> header file. */
#undef HAVE_UCHAR_H
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index eb129dd15d4..ea04a761184 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -37,6 +37,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
RangeTblRef *node = makeNode(RangeTblRef);
+ RangeTblRef *copy = copyObject(node);
List *list = list_make1(node);
foreach_ptr(RangeTblRef, rtr, list)
@@ -54,6 +55,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
list_free(list);
pfree(node);
+ pfree(copy);
switch (a)
{
base-commit: 284925508ae685a63ee056f89a336caecab64a63
--
2.53.0
[text/x-patch] v10-0002-Use-typeof-everywhere-instead-of-compiler-specif.patch (2.3K, 3-v10-0002-Use-typeof-everywhere-instead-of-compiler-specif.patch)
download | inline diff:
From c8fd6666836c7696c49708e1afb785cad3b55f13 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 8 Dec 2025 08:13:51 +0100
Subject: [PATCH v10 2/4] Use typeof everywhere instead of compiler specific
spellings
We define typeof ourselves as __typeof__ if it does not exist. So let's
actually use that for consistency. The meson/autoconf checks for
__builtin_types_compatible_p still use __typeof__ though, because there
we have not redefined it.
---
src/include/c.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index a4fee84398d..df01acdf6ba 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1008,10 +1008,10 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
*/
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
#define StaticAssertVariableIsOfType(varname, typename) \
- StaticAssertDecl(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ StaticAssertDecl(__builtin_types_compatible_p(typeof(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename))
#define StaticAssertVariableIsOfTypeMacro(varname, typename) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ (StaticAssertExpr(__builtin_types_compatible_p(typeof(varname), typename), \
CppAsString(varname) " does not have type " CppAsString(typename)))
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
#define StaticAssertVariableIsOfType(varname, typename) \
@@ -1275,11 +1275,11 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), const underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), volatile underlying_type), \
"wrong cast"), \
(underlying_type) (expr))
#else
--
2.53.0
[text/x-patch] v10-0003-Make-unconstify-and-unvolatize-use-StaticAssertV.patch (1.7K, 4-v10-0003-Make-unconstify-and-unvolatize-use-StaticAssertV.patch)
download | inline diff:
From 8abacdb5305619a19fb3dc7eaa53d4cc4d7d805e Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Thu, 19 Feb 2026 23:55:43 +0100
Subject: [PATCH v10 3/4] Make unconstify and unvolatize use
StaticAssertVariableIsOfTypeMacro
The unconstify and unvolatize macros had an almost identical assertion
as was already defined in StaticAssertVariableIsOfTypeMacro, only it had
a less useful error message and didn't have a sizeof fallback.
---
src/include/c.h | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index df01acdf6ba..c92b214f6b0 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1273,20 +1273,13 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
#if defined(__cplusplus)
#define unconstify(underlying_type, expr) const_cast<underlying_type>(expr)
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
-#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
+#else
#define unconstify(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), const underlying_type), \
- "wrong cast"), \
+ (StaticAssertVariableIsOfTypeMacro(expr, const underlying_type), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
- (StaticAssertExpr(__builtin_types_compatible_p(typeof(expr), volatile underlying_type), \
- "wrong cast"), \
+ (StaticAssertVariableIsOfTypeMacro(expr, volatile underlying_type), \
(underlying_type) (expr))
-#else
-#define unconstify(underlying_type, expr) \
- ((underlying_type) (expr))
-#define unvolatize(underlying_type, expr) \
- ((underlying_type) (expr))
#endif
/*
--
2.53.0
[text/x-patch] v10-0004-Add-C-version-of-__builtin_types_compatible_p.patch (3.7K, 5-v10-0004-Add-C-version-of-__builtin_types_compatible_p.patch)
download | inline diff:
From 437a8aece153c5dc24c0e2708c034fe1718ea3bf Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Fri, 13 Feb 2026 09:39:34 +0100
Subject: [PATCH v10 4/4] Add C++ version of __builtin_types_compatible_p
StaticAssertVariableIsOfType would fail to compile in C++ extensions if
meson/autoconf has detected HAVE__BUILTIN_TYPES_COMPATIBLE_P to be true
for the C compiler. Basically equivalent to the PG_PRINTF_ATTRIBUTE
situation in 0909380e4c9.
This fixes that problem by defining __builtin_types_compatible_p in C++
using an equivalent STL constructs.
---
src/include/c.h | 22 +++++++++++++++++++
.../test_cplusplusext/test_cplusplusext.cpp | 20 ++++++++++++++++-
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/src/include/c.h b/src/include/c.h
index c92b214f6b0..ba629a3503b 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -80,6 +80,12 @@
#ifdef HAVE_XLOCALE_H
#include <xlocale.h>
#endif
+#ifdef __cplusplus
+extern "C++"
+{
+#include <type_traits>
+}
+#endif
#ifdef ENABLE_NLS
#include <libintl.h>
#endif
@@ -443,7 +449,23 @@
#ifndef HAVE_TYPEOF
#define HAVE_TYPEOF 1
#endif
+/*
+ * Provide __builtin_types_compatible_p for C++ by comparing types with
+ * std::is_same after stripping cv-qualifiers. The second branch handles
+ * GCC's special case where an incomplete array (e.g. int[]) is considered
+ * compatible with a complete array of the same element type (e.g. int[3]).
+ */
+#define __builtin_types_compatible_p(x, y) \
+ (std::is_same<std::remove_cv_t<x>, std::remove_cv_t<y>>::value || \
+ (std::is_array<x>::value && std::is_array<y>::value && \
+ (std::extent<x>::value == 0 || std::extent<y>::value == 0) && \
+ std::is_same<std::remove_cv_t<std::remove_extent_t<x>>, \
+ std::remove_cv_t<std::remove_extent_t<y>>>::value))
+#ifndef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1
#endif
+#endif
+
/*
* CppAsString
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index ea04a761184..936ca422c76 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -34,11 +34,14 @@ StaticAssertDecl(sizeof(int32) == 4, "int32 should be 4 bytes");
extern "C" Datum
test_cplusplus_add(PG_FUNCTION_ARGS)
{
- int32 a = PG_GETARG_INT32(0);
+ const int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
+ const char *p = "";
RangeTblRef *node = makeNode(RangeTblRef);
RangeTblRef *copy = copyObject(node);
List *list = list_make1(node);
+ const int32 int_array[3] = {0};
+ extern int32 incomplete_array[];
foreach_ptr(RangeTblRef, rtr, list)
{
@@ -52,6 +55,21 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
StaticAssertStmt(sizeof(int32) == 4, "int32 should be 4 bytes");
(void) StaticAssertExpr(sizeof(int64) == 8, "int64 should be 8 bytes");
+ StaticAssertVariableIsOfType(a, int32);
+ StaticAssertVariableIsOfType(a, const int32);
+ StaticAssertVariableIsOfType(b, const int32);
+ StaticAssertVariableIsOfType(int_array, int32[3]);
+ StaticAssertVariableIsOfType(int_array, const int32[3]);
+ StaticAssertVariableIsOfType(p, const char *);
+ StaticAssertVariableIsOfTypeMacro(a, int32);
+ StaticAssertVariableIsOfTypeMacro(a, const int32);
+ StaticAssertVariableIsOfTypeMacro(b, int32);
+ StaticAssertVariableIsOfTypeMacro(int_array, int32[3]);
+ StaticAssertVariableIsOfTypeMacro(int_array, const int32[3]);
+ StaticAssertVariableIsOfTypeMacro(p, const char *);
+ /* incomplete array matches complete array type */
+ StaticAssertVariableIsOfType(incomplete_array, int32[3]);
+ StaticAssertVariableIsOfTypeMacro(incomplete_array, int32[3]);
list_free(list);
pfree(node);
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-02-27 16:52 ` Peter Eisentraut <[email protected]>
2026-02-28 11:31 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-02-27 16:52 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 27.02.26 17:40, Jelte Fennema-Nio wrote:
> On Fri Feb 20, 2026 at 10:47 AM CET, Jelte Fennema-Nio wrote:
>> Makes total sense, I didn't realise decltype and typeof were not quite
>> the same thing. Attached is an updated patchset that does that.
>
> Same patchset as before, but now also including a C++ fallback for
> __builtin_types_compatible_p.
Have you tested whether/how these configure/meson tests work if no C++
compiler is found?
(I haven't, I'm just wondering.)
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:52 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-02-28 11:31 ` Jelte Fennema-Nio <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-02-28 11:31 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Fri, 27 Feb 2026 at 17:52, Peter Eisentraut <[email protected]> wrote:
> Have you tested whether/how these configure/meson tests work if no C++
> compiler is found?
>
> (I haven't, I'm just wondering.)
I hadn't before, but done now. It compiles postgres without problems
(but without the cplusplusext extension ofcourse). For meson the new
meson checks are inside have_cxx, so they are not run at all. For
configure the checks are run, but they detect typeof as not available
in C++ (because its unable to compile the test program).
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-03-02 10:56 ` Peter Eisentraut <[email protected]>
2026-03-06 09:23 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-03-02 10:56 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 27.02.26 17:40, Jelte Fennema-Nio wrote:
> On Fri Feb 20, 2026 at 10:47 AM CET, Jelte Fennema-Nio wrote:
>> Makes total sense, I didn't realise decltype and typeof were not quite
>> the same thing. Attached is an updated patchset that does that.
>
> Same patchset as before, but now also including a C++ fallback for
> __builtin_types_compatible_p.
I have committed v10-0001. Now let's give the buildfarm a few days.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-02 10:56 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-03-06 09:23 ` Peter Eisentraut <[email protected]>
2026-03-09 08:39 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-03-06 09:23 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 02.03.26 11:56, Peter Eisentraut wrote:
> On 27.02.26 17:40, Jelte Fennema-Nio wrote:
>> On Fri Feb 20, 2026 at 10:47 AM CET, Jelte Fennema-Nio wrote:
>>> Makes total sense, I didn't realise decltype and typeof were not quite
>>> the same thing. Attached is an updated patchset that does that.
>>
>> Same patchset as before, but now also including a C++ fallback for
>> __builtin_types_compatible_p.
>
> I have committed v10-0001. Now let's give the buildfarm a few days.
I have committed v10-0002 and v10-0003 now. I will look at the
remaining patch in a few days.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-02 10:56 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-06 09:23 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-03-09 08:39 ` Peter Eisentraut <[email protected]>
2026-03-13 09:08 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-03-09 08:39 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 06.03.26 10:23, Peter Eisentraut wrote:
> On 02.03.26 11:56, Peter Eisentraut wrote:
>> On 27.02.26 17:40, Jelte Fennema-Nio wrote:
>>> On Fri Feb 20, 2026 at 10:47 AM CET, Jelte Fennema-Nio wrote:
>>>> Makes total sense, I didn't realise decltype and typeof were not quite
>>>> the same thing. Attached is an updated patchset that does that.
>>>
>>> Same patchset as before, but now also including a C++ fallback for
>>> __builtin_types_compatible_p.
>>
>> I have committed v10-0001. Now let's give the buildfarm a few days.
>
> I have committed v10-0002 and v10-0003 now. I will look at the
> remaining patch in a few days.
Thoughts on v10-0004:
It's not clear to me to what extent StaticAssertVariableIsOfType would
be useful in C++. There are two general areas where it is used. One,
when multiple separate extensions want to talk to each other, to check
the types of certain entry point variables, such as
plpython/hstore_plpython. And two, in some macro-based template
libraries such as lib/ilist.h and lib/pairingheap.h. You add a lot of
tests, but do they cover these particular use scenarios?
In either case, it might be better to create a test on that level and
then see what we'd need to make happen to have it working under C++.
There is lots of trickery involved there, so it's not clear whether it
works out of the box in C++ already.
Are there any of these that you are particularly interested in for your
work?
About the specific implementation, I'm hesitant to build this on top of
__builtin_types_compatible_p(). Aside from the ugliness of redefining a
symbol that starts with __builtin_*, I think we should really work to
get rid of __builtin_types_compatible_p() and replace it with _Generic,
which would be portable beyond GCC.
How about we make a pg_types_compatible_p(), which would look like this:
#if defined(__cplusplus)
// your C++ code here
#else if defined(HAVE__GENERIC)
// C code using _Generic here
#else
// C code using __builtin_types_compatible_p here
#endif
We can require that a supported C compiler must support either _Generic
or __builtin_types_compatible_p, so we don't need any further fallback.
(So we could remove the configure test of __builtin_types_compatible_p,
but we'd add one for _Generic.) And in a few years we could even remove
the __builtin_types_compatible_p fallback.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-19 08:31 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-02 10:56 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-06 09:23 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-09 08:39 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-03-13 09:08 ` Jelte Fennema-Nio <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-03-13 09:08 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Mon, 9 Mar 2026 at 09:39, Peter Eisentraut <[email protected]> wrote:
> I think we should really work to
> get rid of __builtin_types_compatible_p() and replace it with _Generic,
> which would be portable beyond GCC.
I initially intended to do this, but sadly using _Generic inside our
static assert constructs (even the new version you added) causes
internal compiler errors on MSVC 19... I agree with your other
feedback, and I think it's probably best to retract this patch (I've
marked it as committeed in the commitfest now, because of all the
other patches). The main reason I cared about this was to have a
_Generic based macro for type comparisons, which I could use in other
patches. I'll just create some there instead.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-03-23 09:58 ` Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2 siblings, 1 reply; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-03-23 09:58 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On Mon, 23 Mar 2026 at 10:27, Peter Eisentraut <[email protected]> wrote:
> I think we should commit the pg_list.h changes, since the C-style
> compound literals are not a C++ feature at all, and so without this MSVC
> would never get supported. (Or you couldn't use PostgreSQL lists, which
> would be very limiting.)
Sounds good to me.
> The other changes deal with designated initializers and flexible array
> members. These are not a blocker, since extension authors could deal
> with them themselves by adding appropriate compiler options or similar.
I think we should add these flags to CXXFLAGS for MSVC by default,
similar to how we add -std=gnu++11/-std=c++11 for other compilers. We
can then document on the C++ extension docs page, that MSVC compilers
require C++20 support.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-03-29 22:53 ` Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-03-29 22:53 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On Fri, 27 Mar 2026 at 12:23, Peter Eisentraut <[email protected]> wrote:
> Here is another tidied up patch set for this. I didn't go quite as far
> as enabling C++20 by default in meson.build, this would just take more
> time to work out and test all the different combinations, but I added
> the flag to the Cirrus CI task, since there we know what compiler we have.
I think 0001 and 0002 are good.
0003 seems awkward though. Attached is an approach that I think is
better: It actually checks for the required featureset and adds the
necessary flags to the compiler.
I also added a small patch in 0004 to align configure and meson
behaviour when no sufficiently modern compiler is found.
Attachments:
[text/x-patch] v12-0001-meson-Make-room-for-C-only-warning-flags-for-MSV.patch (2.3K, 2-v12-0001-meson-Make-room-for-C-only-warning-flags-for-MSV.patch)
download | inline diff:
From 6b04f2bc87231998946ff0736013a98c9f23df2c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Fri, 27 Mar 2026 11:45:36 +0100
Subject: [PATCH v12 1/4] meson: Make room for C++-only warning flags for MSVC
Refactor the MSVC warning option handling to have a list of common
flags and lists of flags specific to C and C++.
---
meson.build | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/meson.build b/meson.build
index ea31cbce9c0..42b0a9a6a71 100644
--- a/meson.build
+++ b/meson.build
@@ -2293,27 +2293,42 @@ endforeach
if cc.get_id() == 'msvc'
- cflags_warn += [
+ msvc_common_warning_flags = [
+ # Disable warnings in system headers
+ '/external:anglebrackets',
+ '/external:W0',
+
# Warnings to disable:
- # from /W1:
- '/wd4090', # different 'modifier' qualifiers
# from /W2:
'/wd4244', # conversion from 'type1' to 'type2', possible loss of data
+
+ # Additional warnings to enable:
+ '/w24062', # enumerator 'identifier' in switch of enum 'enumeration' is not handled [like -Wswitch]
+ '/w24102', # unreferenced label [like -Wunused-label]
+ ]
+
+ msvc_c_warning_flags = [
+ # Warnings to disable:
+ # from /W1:
+ '/wd4090', # different 'modifier' qualifiers
# from /W3:
'/wd4018', # signed/unsigned mismatch
'/wd4101', # unreferenced local variable [like -Wunused-variable, but there is no "unused" attribute, so too noisy]
'/wd4267', # conversion from 'size_t' to 'type', possible loss of data
# Additional warnings to enable:
- '/w24062', # enumerator 'identifier' in switch of enum 'enumeration' is not handled [like -Wswitch]
- '/w24102', # unreferenced label [like -Wunused-label]
'/w24255', # 'function' : no function prototype given: converting '()' to '(void)' [like -Wstrict-prototypes]
+ ]
- # Disable warnings in system headers
- '/external:anglebrackets',
- '/external:W0',
+ msvc_cxx_warning_flags = [
]
+ cflags_warn += msvc_common_warning_flags
+ cflags_warn += msvc_c_warning_flags
+
+ cxxflags_warn += msvc_common_warning_flags
+ cxxflags_warn += msvc_cxx_warning_flags
+
cppflags += [
'/DWIN32',
'/DWINDOWS',
base-commit: 10e4d8aaf46fb46b8b78e026560b68af84a6495b
--
2.53.0
[text/x-patch] v12-0002-Disable-some-C-warnings-in-MSVC.patch (900B, 3-v12-0002-Disable-some-C-warnings-in-MSVC.patch)
download | inline diff:
From 366dfbc11fd047f75107a87023b39a58fa7a2326 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Thu, 26 Mar 2026 08:35:45 +0100
Subject: [PATCH v12 2/4] Disable some C++ warnings in MSVC
Flexible array members, as used in many PostgreSQL header files, are
not a C++ feature. MSVC warns about these. Disable the
warning. (GCC and Clang accept them, but they would warn in -pedantic
mode.)
---
meson.build | 3 +++
1 file changed, 3 insertions(+)
diff --git a/meson.build b/meson.build
index 42b0a9a6a71..64a5bb888d6 100644
--- a/meson.build
+++ b/meson.build
@@ -2321,6 +2321,9 @@ if cc.get_id() == 'msvc'
]
msvc_cxx_warning_flags = [
+ # Warnings to disable:
+ # from /W2:
+ '/wd4200', # nonstandard extension used: zero-sized array in struct/union [widely used in PostgreSQL C headers]
]
cflags_warn += msvc_common_warning_flags
--
2.53.0
[text/x-patch] v12-0003-Add-support-for-C-extensions-with-MSVC.patch (5.7K, 4-v12-0003-Add-support-for-C-extensions-with-MSVC.patch)
download | inline diff:
From df6d9e8d1bb955d9cffe3095cc27d4209de1ce33 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Sun, 29 Mar 2026 13:01:37 +0200
Subject: [PATCH v12 3/4] Add support for C++ extensions with MSVC
To build C++ extensions we need support for designated initializers,
because PG_MODULE_MAGIC uses it. Designated initializers only got
standardized in C++20. In GCC and Clang they also work when using
earlier C++ versions, but MSVC really only supports them when its
configured to be in C++20 mode or higher.
This extends C++11 feature test to also check for designated initializer
support.
When passing both -pedantic and -Werror even Clang and GCC can fail this
new feature test if they're old enough that they don't compile with
C++20 by default. So this also changes meson and configure to try C++20
if using C++11 didn't work. Before this patch this such a setup would
pass the C++11 check but would then fail to compile test_cplusplusext.
---
configure.ac | 13 ++++++----
doc/src/sgml/xfunc.sgml | 5 ++++
meson.build | 26 +++++++++++--------
.../modules/test_cplusplusext/meson.build | 5 ----
4 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/configure.ac b/configure.ac
index 2baac5e9da7..e4570a805c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -398,17 +398,20 @@ AC_SUBST(have_cxx)
if test "$have_cxx" = yes; then
-# Detect option needed for C++11
-AC_MSG_CHECKING([for $CXX option to accept ISO C++11])
+# Detect option needed for C++11 with designated initializers. We need
+# designated initializers because we use them in many of our headers, including
+# in the PG_MODULE_MAGIC definition.
+AC_MSG_CHECKING([for $CXX option to accept ISO C++11 with designated initializers])
AC_CACHE_VAL([pgac_cv_prog_cxx_cxx11],
[pgac_cv_prog_cxx_cxx11=no
pgac_save_CXX=$CXX
AC_LANG_PUSH([C++])
-for pgac_arg in '' '-std=gnu++11' '-std=c++11'; do
+for pgac_arg in '' '-std=gnu++11' '-std=c++11' '-std=gnu++20' '-std=c++20'; do
CXX="$pgac_save_CXX $pgac_arg"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#if !defined __cplusplus || __cplusplus < 201103L
# error "Compiler does not advertise C++11 conformance"
-#endif]])], [[pgac_cv_prog_cxx_cxx11=$pgac_arg]])
+#endif
+struct S { int x; } s = { .x = 1 };]])], [[pgac_cv_prog_cxx_cxx11=$pgac_arg]])
test x"$pgac_cv_prog_cxx_cxx11" != x"no" && break
done
AC_LANG_POP([C++])
@@ -416,7 +419,7 @@ CXX=$pgac_save_CXX])
if test x"$pgac_cv_prog_cxx_cxx11" = x"no"; then
AC_MSG_RESULT([unsupported])
- AC_MSG_WARN([C++ compiler "$CXX" does not support C++11])
+ AC_MSG_WARN([C++ compiler "$CXX" does not support C++11 with designated initializers])
have_cxx=no
elif test x"$pgac_cv_prog_cxx_cxx11" = x""; then
AC_MSG_RESULT([none needed])
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 70e815b8a2c..6895fe483c1 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -4026,6 +4026,11 @@ extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,
<itemizedlist>
<listitem>
+ <para>
+ You need a C++ compiler that supports C++11 and designated
+ initializers (GCC and Clang support this in C++11 mode, but MSVC only
+ supports it in C++20 mode).
+ </para>
<para>
All functions accessed by the backend must present a C interface
to the backend; these C functions can then call C++ functions.
diff --git a/meson.build b/meson.build
index 64a5bb888d6..bcad5f4fc01 100644
--- a/meson.build
+++ b/meson.build
@@ -647,29 +647,33 @@ if not cc.compiles(c11_test, name: 'C11')
endif
-# Do we need an option to enable C++11?
-cxx11_test = '''
+# Do we need an option to enable C++11 and/or designated initializers? We need
+# designated initiliazers because we use them in many of our headers, including
+# in the PG_MODULE_MAGIC definition. Clang and gcc support designated
+# initializers in C++11 mode, but MSVC only supports them in C++20 mode.
+cxx_features_test = '''
#if !defined __cplusplus || __cplusplus < 201103L
# error "Compiler does not advertise C++11 conformance"
#endif
+struct S { int x; } s = { .x = 1 };
'''
-if have_cxx and not cxx.compiles(cxx11_test, name: 'C++11')
- cxx11_ok = false
+if have_cxx and not cxx.compiles(cxx_features_test, name: 'C++11 with designated initializers')
+ cxx_features_ok = false
if cxx.get_id() == 'msvc'
- cxx11_test_args = ['/std:c++14'] # oldest version supported
+ cxx_features_test_args = ['/std:c++20']
else
- cxx11_test_args = ['-std=gnu++11', '-std=c++11']
+ cxx_features_test_args = ['-std=gnu++11', '-std=c++11', '-std=gnu++20', 'std=c++20']
endif
- foreach arg : cxx11_test_args
- if cxx.compiles(cxx11_test, name: 'C++11 with @0@'.format(arg), args: [arg])
- cxx11_ok = true
+ foreach arg : cxx_features_test_args
+ if cxx.compiles(cxx_features_test, name: 'C++11 with designated initializers with @0@'.format(arg), args: [arg])
+ cxx_features_ok = true
cxxflags += arg
break
endif
endforeach
- if not cxx11_ok
- error('C++ compiler does not support C++11')
+ if not cxx_features_ok
+ error('C++ compiler does not support C++11 with designated initializers')
endif
endif
diff --git a/src/test/modules/test_cplusplusext/meson.build b/src/test/modules/test_cplusplusext/meson.build
index d13210ca593..24a9cf16dca 100644
--- a/src/test/modules/test_cplusplusext/meson.build
+++ b/src/test/modules/test_cplusplusext/meson.build
@@ -4,11 +4,6 @@ if not have_cxx
subdir_done()
endif
-# Currently not supported, to be fixed.
-if cc.get_id() == 'msvc'
- subdir_done()
-endif
-
test_cplusplusext_sources = files(
'test_cplusplusext.cpp',
)
--
2.53.0
[text/x-patch] v12-0004-meson-Consider-an-insufficient-C-compiler-a-warn.patch (1005B, 5-v12-0004-meson-Consider-an-insufficient-C-compiler-a-warn.patch)
download | inline diff:
From 3eeeabc4335d2ceef777b20bb1460a38a82baf2d Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 30 Mar 2026 00:45:53 +0200
Subject: [PATCH v12 4/4] meson: Consider an insufficient C++ compiler a
warning
Meson and configure were handling the case of a C++ compiler with an
insufficient feature set differently. In configure, it would be a
warning, but meson would throw a hard error. This makes it a warning in
meson too.
---
meson.build | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index bcad5f4fc01..ef1d7ed9a57 100644
--- a/meson.build
+++ b/meson.build
@@ -673,7 +673,8 @@ if have_cxx and not cxx.compiles(cxx_features_test, name: 'C++11 with designated
endif
endforeach
if not cxx_features_ok
- error('C++ compiler does not support C++11 with designated initializers')
+ warning('C++ compiler does not support C++11 with designated initializers')
+ have_cxx = false
endif
endif
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-03-31 08:33 ` Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-03-31 08:33 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On 30.03.26 00:53, Jelte Fennema-Nio wrote:
> On Fri, 27 Mar 2026 at 12:23, Peter Eisentraut <[email protected]>
> wrote:
>> Here is another tidied up patch set for this. I didn't go quite as far
>> as enabling C++20 by default in meson.build, this would just take more
>> time to work out and test all the different combinations, but I added
>> the flag to the Cirrus CI task, since there we know what compiler we
>> have.
>
> I think 0001 and 0002 are good.
>
> 0003 seems awkward though. Attached is an approach that I think is
> better: It actually checks for the required featureset and adds the
> necessary flags to the compiler.
Hmm, note that C++ is also used for LLVM/JIT, and by requiring this
additional feature set we are also imposing new requirements for those
users. This has not been fully explored, and I hesitate to add such a
new requirement at the last moment.
But how about this: We add the feature test that you propose and enable
the extension based on that. See attached patch. This reduces to
essentially a three-line patch, much simpler than all previous proposals.
From ec7e12b1c0e53a9a1a46d1f43479fdf71d4ba8eb Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 31 Mar 2026 09:48:52 +0200
Subject: [PATCH] Enable test_cplusplusext with MSVC
The test_cplusplusext test module has so far been disabled on MSVC.
The only remaining problem now is that designated initializers, as
used in PG_MODULE_MAGIC, require C++20. (With GCC and Clang they work
in older C++ versions as well.)
This adds another test in the top-level meson.build to check that the
compiler supports C++20 designated initializers. This is not
required, we are just checking and recording the answer. If yes, we
can enable the test module.
Most current compilers likely won't be in C++20 mode by default. This
doesn't change that; we are not doing anything to try to switch the
compiler into that mode. This might be a separate project, but for
now we'll leave that for the user or the test scaffolding.
The VS task on Cirrus CI is changed to provide the required flag to
turn on C++20 mode.
Discussion: https://www.postgresql.org/message-id/flat/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg%40mai...
---
.cirrus.tasks.yml | 1 +
meson.build | 14 ++++++++++++++
src/test/modules/test_cplusplusext/meson.build | 7 +------
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index 0f32827952f..a22cef063f3 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -782,6 +782,7 @@ task:
CIRRUS_WINDOWS_ERROR_MODE: 0x8001
MESON_FEATURES:
+ -Dcpp_args=/std:c++20
-Dauto_features=disabled
-Dldap=enabled
-Dssl=openssl
diff --git a/meson.build b/meson.build
index c4b4cd4af06..8b134b28a69 100644
--- a/meson.build
+++ b/meson.build
@@ -2176,6 +2176,20 @@ choke me
endif
+# Check whether the C++ compiler supports designated initializers.
+# These are used by PG_MODULE_MAGIC, and we use the result of this
+# test to decide whether to enable the test_cplusplusext test module.
+# Designated initializers only got standardized in C++20. In GCC and
+# Clang they also work when using earlier C++ versions, but MSVC
+# really only supports them when its configured to be in C++20 mode or
+# higher.
+if have_cxx
+ have_cxx_desinit = cxx.compiles('struct S { int x; } s = { .x = 1 };', name: 'C++ designated initializers')
+else
+ have_cxx_desinit = false
+endif
+
+
###############################################################
# Compiler flags
diff --git a/src/test/modules/test_cplusplusext/meson.build b/src/test/modules/test_cplusplusext/meson.build
index d13210ca593..5860464a503 100644
--- a/src/test/modules/test_cplusplusext/meson.build
+++ b/src/test/modules/test_cplusplusext/meson.build
@@ -1,11 +1,6 @@
# Copyright (c) 2025-2026, PostgreSQL Global Development Group
-if not have_cxx
- subdir_done()
-endif
-
-# Currently not supported, to be fixed.
-if cc.get_id() == 'msvc'
+if not have_cxx or not have_cxx_desinit
subdir_done()
endif
--
2.53.0
Attachments:
[text/plain] 0001-Enable-test_cplusplusext-with-MSVC.patch (3.0K, 2-0001-Enable-test_cplusplusext-with-MSVC.patch)
download | inline diff:
From ec7e12b1c0e53a9a1a46d1f43479fdf71d4ba8eb Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 31 Mar 2026 09:48:52 +0200
Subject: [PATCH] Enable test_cplusplusext with MSVC
The test_cplusplusext test module has so far been disabled on MSVC.
The only remaining problem now is that designated initializers, as
used in PG_MODULE_MAGIC, require C++20. (With GCC and Clang they work
in older C++ versions as well.)
This adds another test in the top-level meson.build to check that the
compiler supports C++20 designated initializers. This is not
required, we are just checking and recording the answer. If yes, we
can enable the test module.
Most current compilers likely won't be in C++20 mode by default. This
doesn't change that; we are not doing anything to try to switch the
compiler into that mode. This might be a separate project, but for
now we'll leave that for the user or the test scaffolding.
The VS task on Cirrus CI is changed to provide the required flag to
turn on C++20 mode.
Discussion: https://www.postgresql.org/message-id/flat/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg%40mail.gmail.com
---
.cirrus.tasks.yml | 1 +
meson.build | 14 ++++++++++++++
src/test/modules/test_cplusplusext/meson.build | 7 +------
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index 0f32827952f..a22cef063f3 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -782,6 +782,7 @@ task:
CIRRUS_WINDOWS_ERROR_MODE: 0x8001
MESON_FEATURES:
+ -Dcpp_args=/std:c++20
-Dauto_features=disabled
-Dldap=enabled
-Dssl=openssl
diff --git a/meson.build b/meson.build
index c4b4cd4af06..8b134b28a69 100644
--- a/meson.build
+++ b/meson.build
@@ -2176,6 +2176,20 @@ choke me
endif
+# Check whether the C++ compiler supports designated initializers.
+# These are used by PG_MODULE_MAGIC, and we use the result of this
+# test to decide whether to enable the test_cplusplusext test module.
+# Designated initializers only got standardized in C++20. In GCC and
+# Clang they also work when using earlier C++ versions, but MSVC
+# really only supports them when its configured to be in C++20 mode or
+# higher.
+if have_cxx
+ have_cxx_desinit = cxx.compiles('struct S { int x; } s = { .x = 1 };', name: 'C++ designated initializers')
+else
+ have_cxx_desinit = false
+endif
+
+
###############################################################
# Compiler flags
diff --git a/src/test/modules/test_cplusplusext/meson.build b/src/test/modules/test_cplusplusext/meson.build
index d13210ca593..5860464a503 100644
--- a/src/test/modules/test_cplusplusext/meson.build
+++ b/src/test/modules/test_cplusplusext/meson.build
@@ -1,11 +1,6 @@
# Copyright (c) 2025-2026, PostgreSQL Global Development Group
-if not have_cxx
- subdir_done()
-endif
-
-# Currently not supported, to be fixed.
-if cc.get_id() == 'msvc'
+if not have_cxx or not have_cxx_desinit
subdir_done()
endif
--
2.53.0
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-03-31 09:09 ` Jelte Fennema-Nio <[email protected]>
2026-04-01 05:54 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-03-31 09:09 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On Tue, 31 Mar 2026 at 10:33, Peter Eisentraut <[email protected]> wrote:
> Hmm, note that C++ is also used for LLVM/JIT, and by requiring this
> additional feature set we are also imposing new requirements for those
> users. This has not been fully explored, and I hesitate to add such a
> new requirement at the last moment.
I understand the hesitation, but in practice we already impose those
requirements anyway for non-MSVC compilers because test_cplusplusext
doesn't compile without it. So any compiler that would cause problems
with the new featureset would have already complained about that
before.
> But how about this: We add the feature test that you propose and enable
> the extension based on that. See attached patch. This reduces to
> essentially a three-line patch, much simpler than all previous proposals.
If you're still worried, then this sounds like a fine middle-ground
for now. I think we should reconsider adding the automatic /std:c++20
flag for the PG20 dev cycle though.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-04-01 05:54 ` Peter Eisentraut <[email protected]>
2026-04-09 11:41 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-04-01 05:54 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On 31.03.26 11:09, Jelte Fennema-Nio wrote:
> On Tue, 31 Mar 2026 at 10:33, Peter Eisentraut <[email protected]> wrote:
>> Hmm, note that C++ is also used for LLVM/JIT, and by requiring this
>> additional feature set we are also imposing new requirements for those
>> users. This has not been fully explored, and I hesitate to add such a
>> new requirement at the last moment.
>
> I understand the hesitation, but in practice we already impose those
> requirements anyway for non-MSVC compilers because test_cplusplusext
> doesn't compile without it. So any compiler that would cause problems
> with the new featureset would have already complained about that
> before.
>
>> But how about this: We add the feature test that you propose and enable
>> the extension based on that. See attached patch. This reduces to
>> essentially a three-line patch, much simpler than all previous proposals.
>
> If you're still worried, then this sounds like a fine middle-ground
> for now. I think we should reconsider adding the automatic /std:c++20
> flag for the PG20 dev cycle though.
Ok, I have committed the shown patch.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-04-01 05:54 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-04-09 11:41 ` Bertrand Drouvot <[email protected]>
2026-04-14 13:10 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Bertrand Drouvot @ 2026-04-09 11:41 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
Hi,
On Wed, Apr 01, 2026 at 07:54:07AM +0200, Peter Eisentraut wrote:
> On 31.03.26 11:09, Jelte Fennema-Nio wrote:
> > On Tue, 31 Mar 2026 at 10:33, Peter Eisentraut <[email protected]> wrote:
> > > Hmm, note that C++ is also used for LLVM/JIT, and by requiring this
> > > additional feature set we are also imposing new requirements for those
> > > users. This has not been fully explored, and I hesitate to add such a
> > > new requirement at the last moment.
> >
> > I understand the hesitation, but in practice we already impose those
> > requirements anyway for non-MSVC compilers because test_cplusplusext
> > doesn't compile without it. So any compiler that would cause problems
> > with the new featureset would have already complained about that
> > before.
> >
> > > But how about this: We add the feature test that you propose and enable
> > > the extension based on that. See attached patch. This reduces to
> > > essentially a three-line patch, much simpler than all previous proposals.
> >
> > If you're still worried, then this sounds like a fine middle-ground
> > for now. I think we should reconsider adding the automatic /std:c++20
> > flag for the PG20 dev cycle though.
>
> Ok, I have committed the shown patch.
d50c86e74375 added a comment mentionning that StaticAssertStmt is deprecated, so
we really need the one added in test_cplusplusext.cpp?
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-04-01 05:54 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-04-09 11:41 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
@ 2026-04-14 13:10 ` Bertrand Drouvot <[email protected]>
2026-04-16 08:07 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Bertrand Drouvot @ 2026-04-14 13:10 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
Hi,
On Thu, Apr 09, 2026 at 11:41:39AM +0000, Bertrand Drouvot wrote:
> Hi,
>
> On Wed, Apr 01, 2026 at 07:54:07AM +0200, Peter Eisentraut wrote:
> >
> > Ok, I have committed the shown patch.
>
> d50c86e74375 added a comment mentionning that StaticAssertStmt is deprecated, so
> we really need the one added in test_cplusplusext.cpp?
Now that 66ad764c8d5 is in, the only remaining use of StaticAssertStmt() is in
test_cplusplusext.cpp. What about the attached to get rid of it?
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-04-01 05:54 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-04-09 11:41 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
2026-04-14 13:10 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
@ 2026-04-16 08:07 ` Peter Eisentraut <[email protected]>
2026-04-16 11:31 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
0 siblings, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-04-16 08:07 UTC (permalink / raw)
To: Bertrand Drouvot <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
On 14.04.26 15:10, Bertrand Drouvot wrote:
> Hi,
>
> On Thu, Apr 09, 2026 at 11:41:39AM +0000, Bertrand Drouvot wrote:
>> Hi,
>>
>> On Wed, Apr 01, 2026 at 07:54:07AM +0200, Peter Eisentraut wrote:
>>>
>>> Ok, I have committed the shown patch.
>>
>> d50c86e74375 added a comment mentionning that StaticAssertStmt is deprecated, so
>> we really need the one added in test_cplusplusext.cpp?
>
> Now that 66ad764c8d5 is in, the only remaining use of StaticAssertStmt() is in
> test_cplusplusext.cpp. What about the attached to get rid of it?
This is a test module. Even if the construct is deprecated, we can
still test it.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-02-13 10:28 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-04-01 05:54 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-04-09 11:41 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
2026-04-14 13:10 ` Re: Make copyObject work in C++ Bertrand Drouvot <[email protected]>
2026-04-16 08:07 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-04-16 11:31 ` Bertrand Drouvot <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Bertrand Drouvot @ 2026-04-16 11:31 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>; Andres Freund <[email protected]>
Hi,
On Thu, Apr 16, 2026 at 10:07:35AM +0200, Peter Eisentraut wrote:
> On 14.04.26 15:10, Bertrand Drouvot wrote:
> > Hi,
> >
> > On Thu, Apr 09, 2026 at 11:41:39AM +0000, Bertrand Drouvot wrote:
> > > Hi,
> > >
> > > On Wed, Apr 01, 2026 at 07:54:07AM +0200, Peter Eisentraut wrote:
> > > >
> > > > Ok, I have committed the shown patch.
> > >
> > > d50c86e74375 added a comment mentionning that StaticAssertStmt is deprecated, so
> > > we really need the one added in test_cplusplusext.cpp?
> >
> > Now that 66ad764c8d5 is in, the only remaining use of StaticAssertStmt() is in
> > test_cplusplusext.cpp. What about the attached to get rid of it?
>
> This is a test module. Even if the construct is deprecated, we can still
> test it.
Right, but I was thinking that if we introduce a "pg_attribute_deprecated" macro
(like discussed in [1] and [2]) and make use of it for StaticAssertStmt(), then
this test module would generate Warnings.
We can still come back to it should the above be implemented.
[1]: https://postgr.es/m/CA%2BhUKGK2zuRevnNzCpVzLA7ieHnJoYPnDvgtWRcB4pVnOzchhQ%40mail.gmail.com
[2]: https://postgr.es/m/[email protected]
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-01-26 10:29 ` Peter Eisentraut <[email protected]>
2026-01-26 10:43 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
1 sibling, 1 reply; 39+ messages in thread
From: Peter Eisentraut @ 2026-01-26 10:29 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; Andres Freund <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On 25.01.26 18:52, Jelte Fennema-Nio wrote:
> On Sun Jan 25, 2026 at 5:50 PM CET, Andres Freund wrote:
>> I'm pretty sceptical this is the right direction.
>
> The only other option I can think of is not supporting C++ extension on
> MSVC unless they are compiled with C++20 (or later). I don't
> particularly care about Windows C++ extensions myself, so I personally
> would be fine with that choice. It seems a bit harsh, though.
Maybe it would be enough to only support PG_MODULE_MAGIC (without
arguments) in C++ for now.
That would still require removing the named initializers inside
PG_MODULE_MAGIC_DATA(), but that's only an internal change, and it would
not affect C-language users of PG_MODULE_MAGIC_EXT, and we wouldn't lock
ourselves into a particular style in C++.
Then, maybe in a couple of years, when C++20 is more widely available,
we could enable PG_MODULE_MAGIC_EXT for C++, or design an alternative
construct for C++.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Re: Make copyObject work in C++ Andres Freund <[email protected]>
2026-01-25 17:52 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2026-01-26 10:29 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
@ 2026-01-26 10:43 ` Jelte Fennema-Nio <[email protected]>
0 siblings, 0 replies; 39+ messages in thread
From: Jelte Fennema-Nio @ 2026-01-26 10:43 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Andres Freund <[email protected]>; PostgreSQL Hackers <[email protected]>; Thomas Munro <[email protected]>
On Mon, 26 Jan 2026 at 11:29, Peter Eisentraut <[email protected]> wrote:
> Maybe it would be enough to only support PG_MODULE_MAGIC (without
> arguments) in C++ for now.
You mean by explicitly ifdefing out PG_MODULE_MAGIC_EXT to make it
unusable in C++? Or just not adding the additional documentation that
I added in my patch?
I'm currently using PG_MODULE_MAGIC_EXT in the C++ extension that I
maintain, and I'd prefer to continue doing so. Especially because it
(currently) doesn't have to work on MSVC for my purposes.
^ permalink raw reply [nested|flat] 39+ messages in thread
* Re: Make copyObject work in C++
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Re: Make copyObject work in C++ Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Re: Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
@ 2026-02-04 15:54 ` Bryan Green <[email protected]>
1 sibling, 0 replies; 39+ messages in thread
From: Bryan Green @ 2026-02-04 15:54 UTC (permalink / raw)
To: [email protected]
On 1/25/2026 6:42 AM, Jelte Fennema-Nio wrote:
> On Tue Jan 20, 2026 at 5:28 PM CET, Peter Eisentraut wrote:
>> I have split your first patch further. For a start, I left out the
>> PG_MODULE_MAGIC*-related changes and disabled the module under MSVC.
>> This has been committed. I plan to let the buildfarm run with it for
>> a day or two and then add in the basic MSVC support.
>
> To hopefully make your life a bit easier. Here's a rebased version that
> enables the MSVC support again, with an updated commit message.
>
This causes the build to break on VS 2022. Versions prior do not have
support for __typeof_unqual__. This would have led to
HAVE_TYPEOF_UNQUAL being not defined on the buildfarm causing the
fallback to copyObjectImpl() for VS 2019.
When you build on VS 2022 you will get an error:
../src/backend/commands/event_trigger.c(1901): error C2100: you cannot
dereference an operand of type 'void'
VS 2022 (MSVC) does not handle the void * dereference the way gcc/clang
does (thanks to GNU extensions, I believe). It exposes
__typeof_unqual__ even it C11, but enforces strict C semantics on the
void * dereference. To work on this platform the call
copyObject(lfirst(cell)) would need to have a cast to the correct
concrete type: copyObject((Node *)lfirst(cell)).
I was about to update to VS 2026, but now I think I should have an
instance of VS from 2019, 2022, and 2026.
--
Bryan Green
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 39+ messages in thread
end of thread, other threads:[~2026-04-16 11:31 UTC | newest]
Thread overview: 39+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-12-05 14:46 Make copyObject work in C++ Jelte Fennema-Nio <[email protected]>
2025-12-07 19:45 ` Tom Lane <[email protected]>
2025-12-08 08:00 ` Peter Eisentraut <[email protected]>
2025-12-08 14:51 ` Tom Lane <[email protected]>
2025-12-08 15:31 ` Jelte Fennema-Nio <[email protected]>
2025-12-08 08:11 ` Jelte Fennema-Nio <[email protected]>
2025-12-14 16:56 ` Jelte Fennema-Nio <[email protected]>
2025-12-08 07:57 ` Peter Eisentraut <[email protected]>
2025-12-08 08:33 ` David Geier <[email protected]>
2025-12-08 08:52 ` Jelte Fennema-Nio <[email protected]>
2025-12-09 12:58 ` Jelte Fennema-Nio <[email protected]>
2025-12-16 12:28 ` Peter Eisentraut <[email protected]>
2026-01-25 12:42 ` Jelte Fennema-Nio <[email protected]>
2026-01-25 16:50 ` Andres Freund <[email protected]>
2026-01-25 17:52 ` Jelte Fennema-Nio <[email protected]>
2026-01-25 20:06 ` Andres Freund <[email protected]>
2026-02-13 10:28 ` Jelte Fennema-Nio <[email protected]>
2026-02-17 09:24 ` Peter Eisentraut <[email protected]>
2026-02-19 08:31 ` Peter Eisentraut <[email protected]>
2026-02-20 09:47 ` Jelte Fennema-Nio <[email protected]>
2026-02-27 16:40 ` Jelte Fennema-Nio <[email protected]>
2026-02-27 16:52 ` Peter Eisentraut <[email protected]>
2026-02-28 11:31 ` Jelte Fennema-Nio <[email protected]>
2026-03-02 10:56 ` Peter Eisentraut <[email protected]>
2026-03-06 09:23 ` Peter Eisentraut <[email protected]>
2026-03-09 08:39 ` Peter Eisentraut <[email protected]>
2026-03-13 09:08 ` Jelte Fennema-Nio <[email protected]>
2026-03-23 09:58 ` Jelte Fennema-Nio <[email protected]>
2026-03-29 22:53 ` Jelte Fennema-Nio <[email protected]>
2026-03-31 08:33 ` Peter Eisentraut <[email protected]>
2026-03-31 09:09 ` Jelte Fennema-Nio <[email protected]>
2026-04-01 05:54 ` Peter Eisentraut <[email protected]>
2026-04-09 11:41 ` Bertrand Drouvot <[email protected]>
2026-04-14 13:10 ` Bertrand Drouvot <[email protected]>
2026-04-16 08:07 ` Peter Eisentraut <[email protected]>
2026-04-16 11:31 ` Bertrand Drouvot <[email protected]>
2026-01-26 10:29 ` Peter Eisentraut <[email protected]>
2026-01-26 10:43 ` Jelte Fennema-Nio <[email protected]>
2026-02-04 15:54 ` Bryan Green <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox