Make copyObject work in C++

Started by Jelte Fennema-Nio6 days ago10 messages
#1Jelte Fennema-Nio
Jelte Fennema-Nio
postgres@jeltef.nl
1 attachment(s)

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:

v1-0001-Make-copyObject-work-in-C.patchapplication/x-patch; name=v1-0001-Make-copyObject-work-in-C.patch
#2Tom Lane
Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jelte Fennema-Nio (#1)
Re: Make copyObject work in C++

Jelte Fennema-Nio <postgres@jeltef.nl> 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

#3Peter Eisentraut
Peter Eisentraut
peter@eisentraut.org
In reply to: Jelte Fennema-Nio (#1)
1 attachment(s)
Re: Make copyObject work in C++

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?

Attachments:

0001-Change-copyObject-to-use-typeof_unqual.patchtext/plain; charset=UTF-8; name=0001-Change-copyObject-to-use-typeof_unqual.patch
#4Peter Eisentraut
Peter Eisentraut
peter@eisentraut.org
In reply to: Tom Lane (#2)
Re: Make copyObject work in C++

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.

#5Jelte Fennema-Nio
Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Tom Lane (#2)
2 attachment(s)
Re: Make copyObject work in C++

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:

v2-0001-Make-copyObject-work-in-C.patchtext/x-patch; charset=utf-8; name=v2-0001-Make-copyObject-work-in-C.patch
v2-0002-Use-pg_exprtype-instead-of-__typeof__-or-__typeof.patchtext/x-patch; charset=utf-8; name=v2-0002-Use-pg_exprtype-instead-of-__typeof__-or-__typeof.patch
#6David Geier
David Geier
geidav.pg@gmail.com
In reply to: Peter Eisentraut (#3)
Re: Make copyObject work in C++

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

#7Jelte Fennema-Nio
Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: David Geier (#6)
Re: Make copyObject work in C++

On Mon, 8 Dec 2025 at 09:33, David Geier <geidav.pg@gmail.com> 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).

#8Tom Lane
Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#4)
Re: Make copyObject work in C++

Peter Eisentraut <peter@eisentraut.org> 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

#9Jelte Fennema-Nio
Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Tom Lane (#8)
Re: Make copyObject work in C++

On Mon, 8 Dec 2025 at 15:51, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Peter Eisentraut <peter@eisentraut.org> 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]https://godbolt.org/z/fz567hs1r. Compiling
with the latter works fine[2]https://godbolt.org/z/cq1se55bn.

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

#10Jelte Fennema-Nio
Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Peter Eisentraut (#3)
Re: Make copyObject work in C++

On Mon, 8 Dec 2025 at 08:57, Peter Eisentraut <peter@eisentraut.org> 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]https://en.cppreference.com/w/cpp/types/remove_cv.html.

[1]: https://en.cppreference.com/w/cpp/types/remove_cv.html