public inbox for [email protected]
help / color / mirror / Atom feedFrom: Jelte Fennema-Nio <[email protected]>
To: Andres Freund <[email protected]>
Cc: Peter Eisentraut <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Cc: Thomas Munro <[email protected]>
Subject: Re: Make copyObject work in C++
Date: Fri, 13 Feb 2026 11:28:20 +0100
Message-ID: <[email protected]> (raw)
In-Reply-To: <2h2n2gyw2f4ucicbl3drtdkjt2wzf6b2r4wqm7xwks6vpx5j7n@imymv4hkz5jz>
References: <CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg@mail.gmail.com>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<ztktlrqatfj4roqhdjurccb3b4mf5hrycybfrzwupt4xmbwjt4@alrtyxhz5sns>
<[email protected]>
<2h2n2gyw2f4ucicbl3drtdkjt2wzf6b2r4wqm7xwks6vpx5j7n@imymv4hkz5jz>
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
view thread (27+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: Make copyObject work in C++
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox