Change copyObject() to use typeof_unqual
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]/messages/by-id/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg@mail.gmail.com, 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]: /messages/by-id/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg@mail.gmail.com
/messages/by-id/CAGECzQR21OnnKiZO_1rLWO0-16kg1JBxnVq-wymYW0-_1cUNtg@mail.gmail.com
Attachments:
0001-Change-copyObject-to-use-typeof_unqual.patchtext/plain; charset=UTF-8; name=0001-Change-copyObject-to-use-typeof_unqual.patchDownload+101-3
0002-Add-some-const-qualifiers-enabled-by-typeof_unqual-c.patchtext/plain; charset=UTF-8; name=0002-Add-some-const-qualifiers-enabled-by-typeof_unqual-c.patchDownload+44-42
Hi Peter!
On 20.01.2026 10:37, Peter Eisentraut wrote:
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.
Great change. I've ran into that multiple times and had to
un-const-correct my code because of how copyObject() works.
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.)
I'm not too familiar with the build system, so I let someone else review
this part.
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 changes to EvenTriggerCollectSimpleCommand() look good to me.
Are you planning to look at the rest of the code as well? At a quick
glance there seem to be more places that can be changed in similar ways,
e.g. see refresh_matview_datafill().
--
David Geier
Hi,
On 2026-01-20 10:37:35 +0100, Peter Eisentraut wrote:
(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.)
FWIW, we've recently installed a newer msvc version in the image, we could
switch to that if desired.
Greetings,
Andres
On 20.01.26 11:48, David Geier wrote:
Are you planning to look at the rest of the code as well? At a quick
glance there seem to be more places that can be changed in similar ways,
e.g. see refresh_matview_datafill().
I did as much looking as I was planning for this. If you find more
things to improve, please go ahead.
On 20.01.26 10:37, Peter Eisentraut wrote:
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 *.
I committed this first part, but it ran into some trouble on the buildfarm:
https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=taipan&dt=2026-02-04%2008%3A39%3A34
The problem is that configure detected that gcc supports typeof_unqual,
but the clang used to produce the .bc files does not.
This seems to be a possible problem in general, if we do all these
configure checks with $CC, but then run $CLANG assuming all the results
hold.
My first attempt to fix this was to set CLANG='clang -std=gnu23' to
effectively put clang into approximately the same mode as gcc. This
fixes this particular issue but then later fails when compiling .bc
files for the test_cplusplus module:
clang -std=gnu23 -xc++ -Wno-ignored-attributes -O2 -I. -I.
-I../../../../src/include -D_GNU_SOURCE -I/usr/include/libxml2
-flto=thin -emit-llvm -c -o test_cplusplusext.bc test_cplusplusext.cpp
error: invalid argument '-std=gnu23' not allowed with 'C++'
This might be another looming problem. Do we need to look up, say,
CLANGXX separately from CLANG?
Another attempt was to switch the order of the configure test to check
for __typeof_unqual__ before typeof_unqual. This works, but it seems
totally unprincipled.
Any thoughts?
(Btw., the buildfarm member description says gcc 13, but it's actually
using gcc 15.)
Peter Eisentraut <peter@eisentraut.org> writes:
Another attempt was to switch the order of the configure test to check
for __typeof_unqual__ before typeof_unqual. This works, but it seems
totally unprincipled.
Seems perfectly reasonable from here.
regards, tom lane
On 04.02.26 11:46, Peter Eisentraut wrote:
On 20.01.26 10:37, Peter Eisentraut wrote:
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 *.I committed this first part, but it ran into some trouble on the buildfarm:
https://buildfarm.postgresql.org/cgi-bin/show_log.pl?
nm=taipan&dt=2026-02-04%2008%3A39%3A34The problem is that configure detected that gcc supports typeof_unqual,
but the clang used to produce the .bc files does not.
Here is a new version, after the previous one was reverted.
This is rebased over commit 1887d822f14 and now also provides a C++
implementation, corresponding to the C++ typeof implementation added by
that commit.
This revealed an insufficiency in that commit, which I fix in the first
patch.
I have addressed the above problem by swapping the order of the probes
(putting the underscore variant first), as discussed.
There was also an issue that newer MSVC versions claimed to support
typeof_unqual but it didn't work correctly. I have enhanced the
configure probes to detect this problem.
Attachments:
v2-0001-Fixes-for-C-typeof-implementation.patchtext/plain; charset=UTF-8; name=v2-0001-Fixes-for-C-typeof-implementation.patchDownload+9-1
v2-0002-Change-copyObject-to-use-typeof_unqual.patchtext/plain; charset=UTF-8; name=v2-0002-Change-copyObject-to-use-typeof_unqual.patchDownload+267-4
v2-0003-Add-some-const-qualifiers-enabled-by-typeof_unqua.patchtext/plain; charset=UTF-8; name=v2-0003-Add-some-const-qualifiers-enabled-by-typeof_unqua.patchDownload+44-42
On Fri, 6 Mar 2026 at 20:17, Peter Eisentraut <peter@eisentraut.org> wrote:
This revealed an insufficiency in that commit, which I fix in the first
patch.
Thanks!
I have addressed the above problem by swapping the order of the probes
(putting the underscore variant first), as discussed.
Annoying that this is needed, but I agree that it's the least bad
option in this case.
On 07.03.26 01:17, Jelte Fennema-Nio wrote:
On Fri, 6 Mar 2026 at 20:17, Peter Eisentraut <peter@eisentraut.org> wrote:
This revealed an insufficiency in that commit, which I fix in the first
patch.Thanks!
There is a failure related to this on buildfarm member sevengill:
../pgsql/src/test/modules/test_cplusplusext/test_cplusplusext.cpp:41:22:
error: no template named 'remove_reference_t' in namespace 'std'; did
you mean 'remove_reference'?
I don't know how that makes sense. Maybe this is a problem in the local
installation of the compiler or standard library.
(This is also a bit suspicious because AFAICT, clang 15 defaults to
C++14, but on that animal it thinks it needs to add -std=gnu++11.)
I have addressed the above problem by swapping the order of the probes
(putting the underscore variant first), as discussed.Annoying that this is needed, but I agree that it's the least bad
option in this case.
I committed this and it still fails, but the failure is now narrower.
There is a failure on buildfarm member taipan because it uses an unusual
combination of gcc and clang (the gcc is much newer than clang). The
only sensible workaround I could think of is a hardcoded override based
on the clang version, as in the attached patch. And alternative is that
we decide that we don't want to support this combination, meaning that
we would effectively require that clang is approximately as-old-or-newer
than gcc.
Attachments:
0001-Hardcode-override-of-typeof_unqual-for-clang-for-bit.patchtext/plain; charset=UTF-8; name=0001-Hardcode-override-of-typeof_unqual-for-clang-for-bit.patchDownload+15-1
On 13 Mar 2026, at 11:43, Peter Eisentraut <peter@eisentraut.org> wrote:
I committed this and it still fails, but the failure is now narrower. There is a failure on buildfarm member taipan because it uses an unusual combination of gcc and clang (the gcc is much newer than clang). The only sensible workaround I could think of is a hardcoded override based on the clang version, as in the attached patch. And alternative is that we decide that we don't want to support this combination, meaning that we would effectively require that clang is approximately as-old-or-newer than gcc.
I ran into this as well on clang 15 via XCode with no gcc involved:
../src/test/modules/test_cplusplusext/test_cplusplusext.cpp:41:22: error: no template named 'remove_reference_t' in namespace 'std'; did you mean 'remove_reference'?
RangeTblRef *copy = copyObject(nodec);
^~~~~~~~~~~~~~~~~
--
Daniel Gustafsson
On 13.03.26 14:03, Daniel Gustafsson wrote:
On 13 Mar 2026, at 11:43, Peter Eisentraut <peter@eisentraut.org> wrote:
I committed this and it still fails, but the failure is now narrower. There is a failure on buildfarm member taipan because it uses an unusual combination of gcc and clang (the gcc is much newer than clang). The only sensible workaround I could think of is a hardcoded override based on the clang version, as in the attached patch. And alternative is that we decide that we don't want to support this combination, meaning that we would effectively require that clang is approximately as-old-or-newer than gcc.
I ran into this as well on clang 15 via XCode with no gcc involved:
../src/test/modules/test_cplusplusext/test_cplusplusext.cpp:41:22: error: no template named 'remove_reference_t' in namespace 'std'; did you mean 'remove_reference'?
RangeTblRef *copy = copyObject(nodec);
^~~~~~~~~~~~~~~~~
Jelte,
I read here
https://en.cppreference.com/w/cpp/types/remove_reference.html
that remove_reference_t is actually in C++14, which might explain this
failure, if the compiler is in C++11 mode.
I don't understand the difference between remove_reference and
remove_reference_t.
On Fri, 13 Mar 2026 at 17:00, Peter Eisentraut <peter@eisentraut.org> wrote:
that remove_reference_t is actually in C++14, which might explain this
failure, if the compiler is in C++11 mode.
Yeah that's almost certainly it... Sorry about that.
I don't understand the difference between remove_reference and
remove_reference_t.
They are equivalent only the _t version as a bit less verbose.
Attached should fix it.
Attachments:
fix.patchtext/x-patch; charset=US-ASCII; name=fix.patchDownload+1-1
On Fri, 13 Mar 2026 at 17:15, Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
Attached should fix it.
Okay corrected in this v2, which fixes all of the places I could find.
Attachments:
fix-v2.patchtext/x-patch; charset=US-ASCII; name=fix-v2.patchDownload+2-2
On 13.03.26 17:18, Jelte Fennema-Nio wrote:
On Fri, 13 Mar 2026 at 17:15, Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
Attached should fix it.
Okay corrected in this v2, which fixes all of the places I could find.
This doesn't appear to work in this example program:
```
#include <type_traits>
#define mytypeof(x) std::remove_reference<decltype(x)>::value
void foo(void)
{
int a;
mytypeof(a) b;
}
```
Based on some internet search, it appears that ::type would work. But
it also appears to work without either one.
On Sat, 14 Mar 2026 at 14:03, Peter Eisentraut <peter@eisentraut.org> wrote:
This doesn't appear to work in this example program:
Ugh, I should not send emails end of day on a friday in a rush.
Attached is fixed v3 which uses ::type instead.
I was able to reproduce the compilation errors on my machine by using
CXXFLAGS='-std=c++11' when configuring meson, and this patch fixes them.
I think it would be good if we would run one of our CI jobs in c11 and
c++11 (non-gnu) mode so we catch these kind of issues before hitting the
build farm.
Attachments:
v3-0001-Make-typeof-and-typeof_unqual-fallback-definition.patchtext/x-patch; charset=utf-8; name=v3-0001-Make-typeof-and-typeof_unqual-fallback-definition.patchDownload+2-3
On Fri, 13 Mar 2026 at 11:43, Peter Eisentraut <peter@eisentraut.org> wrote:
There is a failure on buildfarm member taipan because it uses an unusual
combination of gcc and clang (the gcc is much newer than clang). The
only sensible workaround I could think of is a hardcoded override based
on the clang version, as in the attached patch.
If we can then start prefering typeof_unqual over __typeof_unqual__ in
the configure check for CC, then I think I like this as a workaround.
If not, then I'm starting to think that actually checking support for
this feature for CLANG is probably easier to understand (and less
fragile) than combining all of these tricks together. Attached is a
patch to do so.
This only does it for CLANG, not for CLANG compiling C++ files.
Theoretically that could be necessary, but I couldn't find a C++
compiler that supports any spelling of typeof_unqual. So I'm not even
sure we need the current CXX check for typeof_unqual, I think we could
remove that too and always use the fallback.
And alternative is that
we decide that we don't want to support this combination, meaning that
we would effectively require that clang is approximately as-old-or-newer
than gcc.
Given that Tom seems to have reproduced this on Fedora 40, it sounds
like we should fix it.
Attachments:
v1-0001-Check-CLANG-for-typeof_unqual.patchtext/x-patch; charset=utf-8; name=v1-0001-Check-CLANG-for-typeof_unqual.patchDownload+123-17
"Jelte Fennema-Nio" <postgres@jeltef.nl> writes:
If not, then I'm starting to think that actually checking support for
this feature for CLANG is probably easier to understand (and less
fragile) than combining all of these tricks together. Attached is a
patch to do so.
+1 for concept, but don't you need to fix meson.build too?
And alternative is that
we decide that we don't want to support this combination, meaning that
we would effectively require that clang is approximately as-old-or-newer
than gcc.
Given that Tom seems to have reproduced this on Fedora 40, it sounds
like we should fix it.
Yeah. Given Fedora's development cycle, it is a certainty that they
shipped gcc and clang versions no more than a couple months different
in age. So even if we wanted to adopt the restriction Peter suggests,
there are not-very-old systems on which it fails.
regards, tom lane
On Sun, 15 Mar 2026 at 23:13, Tom Lane <tgl@sss.pgh.pa.us> wrote:
"Jelte Fennema-Nio" <postgres@jeltef.nl> writes:
If not, then I'm starting to think that actually checking support for
this feature for CLANG is probably easier to understand (and less
fragile) than combining all of these tricks together. Attached is a
patch to do so.+1 for concept, but don't you need to fix meson.build too?
I believe that we don't have fully working bc compilation for meson[1]/messages/by-id/206b001d-1884-4081-bd02-bed5c92f02ba@eisentraut.org,
so I'm not entirely sure how to test out if it actually works. But the
attached now does *something* for meson too at least.
[1]: /messages/by-id/206b001d-1884-4081-bd02-bed5c92f02ba@eisentraut.org
Attachments:
v2-0001-Check-CLANG-for-typeof_unqual.patchtext/x-patch; charset=utf-8; name=v2-0001-Check-CLANG-for-typeof_unqual.patchDownload+170-24
On 16.03.26 00:57, Jelte Fennema-Nio wrote:
On Sun, 15 Mar 2026 at 23:13, Tom Lane <tgl@sss.pgh.pa.us> wrote:
"Jelte Fennema-Nio" <postgres@jeltef.nl> writes:
If not, then I'm starting to think that actually checking support for
this feature for CLANG is probably easier to understand (and less
fragile) than combining all of these tricks together. Attached is a
patch to do so.+1 for concept, but don't you need to fix meson.build too?
I believe that we don't have fully working bc compilation for meson[1],
so I'm not entirely sure how to test out if it actually works. But the
attached now does *something* for meson too at least.
Yeah, this is tricky to analyze and test because the bc compilation
doesn't even exist yet.
I'm tempted to go with my proposed patch of a version-based override for
the time being.
On Mon, 16 Mar 2026 at 13:47, Peter Eisentraut <peter@eisentraut.org> wrote:
I'm tempted to go with my proposed patch of a version-based override for
the time being.
Sounds good to me. But let's not forget to swap back the order of
detection for typeof_unqual vs __typeof_unqual__. Afaict that's not
needed anymore and the comment there only becomes confusing with this
new fix.
Also, it might be nice to only do your version based override, if
we're actually compiling bitcode. In my patch I used
-DPG_COMPILING_BITCODE for that. Otherwise this override can also
happen for regular compiles using clang, which I think would be a bit
confusing.