mirror of
https://github.com/postgres/postgres.git
synced 2026-04-22 22:59:54 -04:00
Support using copyObject in standard C++
Calling copyObject in C++ without GNU extensions (e.g. when 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 used to compile PostgreSQL supporting
typeof, but that function actually not being present in the C++
compiler. This fixes that by explicitely checking for typeof support
in C++, and then either use that or define typeof ourselves as:
std::remove_reference_t<decltype(x)>
According to the paper that led to adding typeof to the C standard,
that's the C++ equivalent of the C typeof:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
Author: Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://www.postgresql.org/message-id/flat/DGPW5WCFY7WY.1IHCDNIVVT300%2540jeltef.nl
This commit is contained in:
parent
386ca3908d
commit
1887d822f1
7 changed files with 139 additions and 0 deletions
|
|
@ -193,6 +193,35 @@ fi])# PGAC_C_TYPEOF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# PGAC_CXX_TYPEOF
|
||||||
|
# ----------------
|
||||||
|
# Check if the C++ compiler understands typeof or a variant. Define
|
||||||
|
# HAVE_CXX_TYPEOF if so, and define 'pg_cxx_typeof' to the actual key word.
|
||||||
|
#
|
||||||
|
AC_DEFUN([PGAC_CXX_TYPEOF],
|
||||||
|
[AC_CACHE_CHECK(for C++ typeof, pgac_cv_cxx_typeof,
|
||||||
|
[pgac_cv_cxx_typeof=no
|
||||||
|
AC_LANG_PUSH(C++)
|
||||||
|
for pgac_kw in typeof __typeof__; do
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
|
||||||
|
[int x = 0;
|
||||||
|
$pgac_kw(x) y;
|
||||||
|
y = x;
|
||||||
|
return y;])],
|
||||||
|
[pgac_cv_cxx_typeof=$pgac_kw])
|
||||||
|
test "$pgac_cv_cxx_typeof" != no && break
|
||||||
|
done
|
||||||
|
AC_LANG_POP([])])
|
||||||
|
if test "$pgac_cv_cxx_typeof" != no; then
|
||||||
|
AC_DEFINE(HAVE_CXX_TYPEOF, 1,
|
||||||
|
[Define to 1 if your C++ compiler understands `typeof' or something similar.])
|
||||||
|
if test "$pgac_cv_cxx_typeof" != typeof; then
|
||||||
|
AC_DEFINE_UNQUOTED(pg_cxx_typeof, $pgac_cv_cxx_typeof, [Define to how the C++ compiler spells `typeof'.])
|
||||||
|
fi
|
||||||
|
fi])# PGAC_CXX_TYPEOF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# PGAC_C_TYPES_COMPATIBLE
|
# PGAC_C_TYPES_COMPATIBLE
|
||||||
# -----------------------
|
# -----------------------
|
||||||
# Check if the C compiler understands __builtin_types_compatible_p,
|
# Check if the C compiler understands __builtin_types_compatible_p,
|
||||||
|
|
|
||||||
54
configure
vendored
54
configure
vendored
|
|
@ -15078,6 +15078,60 @@ _ACEOF
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ typeof" >&5
|
||||||
|
$as_echo_n "checking for C++ typeof... " >&6; }
|
||||||
|
if ${pgac_cv_cxx_typeof+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
pgac_cv_cxx_typeof=no
|
||||||
|
ac_ext=cpp
|
||||||
|
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||||
|
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||||
|
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||||
|
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||||
|
|
||||||
|
for pgac_kw in typeof __typeof__; do
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
$pgac_kw(x) y;
|
||||||
|
y = x;
|
||||||
|
return y;
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
pgac_cv_cxx_typeof=$pgac_kw
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
test "$pgac_cv_cxx_typeof" != no && break
|
||||||
|
done
|
||||||
|
ac_ext=c
|
||||||
|
ac_cpp='$CPP $CPPFLAGS'
|
||||||
|
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||||
|
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||||
|
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||||
|
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_cxx_typeof" >&5
|
||||||
|
$as_echo "$pgac_cv_cxx_typeof" >&6; }
|
||||||
|
if test "$pgac_cv_cxx_typeof" != no; then
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_CXX_TYPEOF 1" >>confdefs.h
|
||||||
|
|
||||||
|
if test "$pgac_cv_cxx_typeof" != typeof; then
|
||||||
|
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define pg_cxx_typeof $pgac_cv_cxx_typeof
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
|
||||||
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
|
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
|
||||||
if ${pgac_cv__types_compatible+:} false; then :
|
if ${pgac_cv__types_compatible+:} false; then :
|
||||||
|
|
|
||||||
|
|
@ -1732,6 +1732,7 @@ PGAC_PRINTF_ARCHETYPE
|
||||||
PGAC_CXX_PRINTF_ARCHETYPE
|
PGAC_CXX_PRINTF_ARCHETYPE
|
||||||
PGAC_C_STATEMENT_EXPRESSIONS
|
PGAC_C_STATEMENT_EXPRESSIONS
|
||||||
PGAC_C_TYPEOF
|
PGAC_C_TYPEOF
|
||||||
|
PGAC_CXX_TYPEOF
|
||||||
PGAC_C_TYPES_COMPATIBLE
|
PGAC_C_TYPES_COMPATIBLE
|
||||||
PGAC_C_BUILTIN_CONSTANT_P
|
PGAC_C_BUILTIN_CONSTANT_P
|
||||||
PGAC_C_BUILTIN_OP_OVERFLOW
|
PGAC_C_BUILTIN_OP_OVERFLOW
|
||||||
|
|
|
||||||
25
meson.build
25
meson.build
|
|
@ -2953,6 +2953,31 @@ int main(void)
|
||||||
endif
|
endif
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
# Check if the C++ compiler understands typeof or a variant.
|
||||||
|
if have_cxx
|
||||||
|
foreach kw : ['typeof', '__typeof__']
|
||||||
|
if cxx.compiles('''
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
@0@(x) y;
|
||||||
|
y = x;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
'''.format(kw),
|
||||||
|
name: 'C++ ' + kw,
|
||||||
|
args: test_c_args, include_directories: postgres_inc)
|
||||||
|
|
||||||
|
cdata.set('HAVE_CXX_TYPEOF', 1)
|
||||||
|
if kw != 'typeof'
|
||||||
|
cdata.set('pg_cxx_typeof', kw)
|
||||||
|
endif
|
||||||
|
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# MSVC doesn't cope well with defining restrict to __restrict, the
|
# MSVC doesn't cope well with defining restrict to __restrict, the
|
||||||
# spelling it understands, because it conflicts with
|
# spelling it understands, because it conflicts with
|
||||||
|
|
|
||||||
|
|
@ -424,6 +424,27 @@
|
||||||
#define unlikely(x) ((x) != 0)
|
#define unlikely(x) ((x) != 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Provide typeof in C++ for C++ compilers that don't support typeof natively.
|
||||||
|
* It might be spelled __typeof__ instead of typeof, in which case
|
||||||
|
* pg_cxx_typeof provides that mapping. If neither is supported, we can use
|
||||||
|
* decltype, but to make it equivalent to C's typeof, we need to remove
|
||||||
|
* references from the result [1]. Also ensure HAVE_TYPEOF is set so that
|
||||||
|
* typeof-dependent code is always enabled in C++ mode.
|
||||||
|
*
|
||||||
|
* [1]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
|
||||||
|
*/
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#ifdef pg_cxx_typeof
|
||||||
|
#define typeof(x) pg_cxx_typeof(x)
|
||||||
|
#elif !defined(HAVE_CXX_TYPEOF)
|
||||||
|
#define typeof(x) std::remove_reference_t<decltype(x)>
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_TYPEOF
|
||||||
|
#define HAVE_TYPEOF 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CppAsString
|
* CppAsString
|
||||||
* Convert the argument to a string, using the C preprocessor.
|
* Convert the argument to a string, using the C preprocessor.
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,10 @@
|
||||||
/* Define to 1 if you have the <crtdefs.h> header file. */
|
/* Define to 1 if you have the <crtdefs.h> header file. */
|
||||||
#undef HAVE_CRTDEFS_H
|
#undef HAVE_CRTDEFS_H
|
||||||
|
|
||||||
|
/* Define to 1 if your C++ compiler understands `typeof' or something similar.
|
||||||
|
*/
|
||||||
|
#undef HAVE_CXX_TYPEOF
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
|
/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
|
||||||
don't. */
|
don't. */
|
||||||
#undef HAVE_DECL_FDATASYNC
|
#undef HAVE_DECL_FDATASYNC
|
||||||
|
|
@ -780,6 +784,9 @@
|
||||||
/* Define for large files, on AIX-style hosts. */
|
/* Define for large files, on AIX-style hosts. */
|
||||||
#undef _LARGE_FILES
|
#undef _LARGE_FILES
|
||||||
|
|
||||||
|
/* Define to how the C++ compiler spells `typeof'. */
|
||||||
|
#undef pg_cxx_typeof
|
||||||
|
|
||||||
/* Define to keyword to use for C99 restrict support, or to nothing if not
|
/* Define to keyword to use for C99 restrict support, or to nothing if not
|
||||||
supported */
|
supported */
|
||||||
#undef pg_restrict
|
#undef pg_restrict
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
|
||||||
int32 a = PG_GETARG_INT32(0);
|
int32 a = PG_GETARG_INT32(0);
|
||||||
int32 b = PG_GETARG_INT32(1);
|
int32 b = PG_GETARG_INT32(1);
|
||||||
RangeTblRef *node = makeNode(RangeTblRef);
|
RangeTblRef *node = makeNode(RangeTblRef);
|
||||||
|
RangeTblRef *copy = copyObject(node);
|
||||||
List *list = list_make1(node);
|
List *list = list_make1(node);
|
||||||
|
|
||||||
foreach_ptr(RangeTblRef, rtr, list)
|
foreach_ptr(RangeTblRef, rtr, list)
|
||||||
|
|
@ -54,6 +55,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
list_free(list);
|
list_free(list);
|
||||||
pfree(node);
|
pfree(node);
|
||||||
|
pfree(copy);
|
||||||
|
|
||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue