Change copyObject() to use typeof_unqual

Peter Eisentraut <peter@eisentraut.org>

From: Peter Eisentraut <peter@eisentraut.org>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2026-01-20T09:37:35Z
Lists: pgsql-hackers

Attachments

Currently, when the argument of copyObject() is const-qualified, the 
return type is also, because the use of typeof carries over all the 
qualifiers.  This is incorrect, since the point of copyObject() is to 
  make a copy to mutate.  But apparently no code ran into it.

The new implementation uses typeof_unqual, which drops the qualifiers, 
making this work correctly.

typeof_unqual is standardized in C23, but all recent versions of all the 
usual compilers support it even in non-C23 mode, at least as 
__typeof_unqual__.  We add a configure/meson test for typeof_unqual and 
__typeof_unqual__ and use it if it's available, else we use the existing 
fallback of just returning void *.

(Even MSVC supports it, if we use a slightly newer version than is on 
CI.  For example, the new buildfarm member unicorn would support it.)

The second patch make some changes to take advantage of this improved 
qualifier handling.  EventTriggerCollectSimpleCommand() is a good 
example:  It takes a node tree and makes a copy that it keeps around for 
its internal purposes, but it can't communicate via its function 
signature that it promises not scribble on the passed node tree.  That 
is now fixed.

The obvious drawback is that if you use an older compiler that supports 
typeof but not typeof_unqual, this change will make you lose that check. 
  Currently, on the Cirrus CI system, only the NetBSD and OpenBSD tasks 
are affected by this.

Anyway, the reason I'm posting this now instead of, say, waiting another 
year, is that over in the thread "Make copyObject work in C++"[0], we're 
discussing, well, making copyObject() work in (standard) C++ (typeof and 
typeof_unqual are not in C++).  Assuming we want to make the 
typeof_unqual change in principle, I figured it would be worth 
considering doing that change first and then developing a C++ equivalent 
of that, instead of making a C++ equivalent of the current logic and 
then having to find another C++ solution when changing to typeof_unqual.


[0]: 
https://www.postgresql.org/message-id/flat/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg@mail.gmail.com

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Add some const qualifiers enabled by typeof_unqual change on copyObject

  2. Hardcode typeof_unqual to __typeof_unqual__ for clang

  3. Clean up postgres_fdw/t/010_subscription.pl.

  4. Hardcode override of typeof_unqual for clang-for-bitcode

  5. Make typeof and typeof_unqual fallback definitions work on C++11

  6. Change copyObject() to use typeof_unqual

  7. Fixes for C++ typeof implementation

  8. Support using copyObject in standard C++