mirror of
https://github.com/postgres/postgres.git
synced 2026-03-23 10:55:21 -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
|
||||
# -----------------------
|
||||
# Check if the C compiler understands __builtin_types_compatible_p,
|
||||
|
|
|
|||
54
configure
vendored
54
configure
vendored
|
|
@ -15078,6 +15078,60 @@ _ACEOF
|
|||
|
||||
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_n "checking for __builtin_types_compatible_p... " >&6; }
|
||||
if ${pgac_cv__types_compatible+:} false; then :
|
||||
|
|
|
|||
|
|
@ -1732,6 +1732,7 @@ PGAC_PRINTF_ARCHETYPE
|
|||
PGAC_CXX_PRINTF_ARCHETYPE
|
||||
PGAC_C_STATEMENT_EXPRESSIONS
|
||||
PGAC_C_TYPEOF
|
||||
PGAC_CXX_TYPEOF
|
||||
PGAC_C_TYPES_COMPATIBLE
|
||||
PGAC_C_BUILTIN_CONSTANT_P
|
||||
PGAC_C_BUILTIN_OP_OVERFLOW
|
||||
|
|
|
|||
25
meson.build
25
meson.build
|
|
@ -2953,6 +2953,31 @@ int main(void)
|
|||
endif
|
||||
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
|
||||
# spelling it understands, because it conflicts with
|
||||
|
|
|
|||
|
|
@ -424,6 +424,27 @@
|
|||
#define unlikely(x) ((x) != 0)
|
||||
#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
|
||||
* 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. */
|
||||
#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
|
||||
don't. */
|
||||
#undef HAVE_DECL_FDATASYNC
|
||||
|
|
@ -780,6 +784,9 @@
|
|||
/* Define for large files, on AIX-style hosts. */
|
||||
#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
|
||||
supported */
|
||||
#undef pg_restrict
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
|
|||
int32 a = PG_GETARG_INT32(0);
|
||||
int32 b = PG_GETARG_INT32(1);
|
||||
RangeTblRef *node = makeNode(RangeTblRef);
|
||||
RangeTblRef *copy = copyObject(node);
|
||||
List *list = list_make1(node);
|
||||
|
||||
foreach_ptr(RangeTblRef, rtr, list)
|
||||
|
|
@ -54,6 +55,7 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
|
|||
|
||||
list_free(list);
|
||||
pfree(node);
|
||||
pfree(copy);
|
||||
|
||||
switch (a)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue