Re: Make copyObject work in C++ - Mailing list pgsql-hackers

From Jelte Fennema-Nio
Subject Re: Make copyObject work in C++
Date
Msg-id DFXV193BOBQ8.1BY2PK8YRJ9O1@jeltef.nl
Whole thread Raw
In response to Re: Make copyObject work in C++  (Andres Freund <andres@anarazel.de>)
Responses Re: Make copyObject work in C++
Re: Make copyObject work in C++
List pgsql-hackers
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
initializersin 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.



pgsql-hackers by date:

Previous
From: Sami Imseih
Date:
Subject: Re: Optional skipping of unchanged relations during ANALYZE?
Next
From: Mihail Nikalayeu
Date:
Subject: Re: Issues with ON CONFLICT UPDATE and REINDEX CONCURRENTLY