mirror of https://github.com/postgres/postgres
Add infrastructure for compile-time assertions about variable types.
Currently, the macros only work with fairly recent gcc versions, but there is room to expand them to other compilers that have comparable features. Heavily revised and autoconfiscated version of a patch by Andres Freund.
This commit is contained in:
parent
26fd82ddf1
commit
ea473fb2de
|
@ -121,6 +121,46 @@ fi])# PGAC_C_FUNCNAME_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# PGAC_C_STATIC_ASSERT
|
||||||
|
# -----------------------
|
||||||
|
# Check if the C compiler understands _Static_assert(),
|
||||||
|
# and define HAVE__STATIC_ASSERT if so.
|
||||||
|
#
|
||||||
|
# We actually check the syntax ({ _Static_assert(...) }), because we need
|
||||||
|
# gcc-style compound expressions to be able to wrap the thing into macros.
|
||||||
|
AC_DEFUN([PGAC_C_STATIC_ASSERT],
|
||||||
|
[AC_CACHE_CHECK(for _Static_assert, pgac_cv__static_assert,
|
||||||
|
[AC_TRY_LINK([],
|
||||||
|
[({ _Static_assert(1, "foo"); })],
|
||||||
|
[pgac_cv__static_assert=yes],
|
||||||
|
[pgac_cv__static_assert=no])])
|
||||||
|
if test x"$pgac_cv__static_assert" = xyes ; then
|
||||||
|
AC_DEFINE(HAVE__STATIC_ASSERT, 1,
|
||||||
|
[Define to 1 if your compiler understands _Static_assert.])
|
||||||
|
fi])# PGAC_C_STATIC_ASSERT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# PGAC_C_TYPES_COMPATIBLE
|
||||||
|
# -----------------------
|
||||||
|
# Check if the C compiler understands __builtin_types_compatible_p,
|
||||||
|
# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
|
||||||
|
#
|
||||||
|
# We check usage with __typeof__, though it's unlikely any compiler would
|
||||||
|
# have the former and not the latter.
|
||||||
|
AC_DEFUN([PGAC_C_TYPES_COMPATIBLE],
|
||||||
|
[AC_CACHE_CHECK(for __builtin_types_compatible_p, pgac_cv__types_compatible,
|
||||||
|
[AC_TRY_COMPILE([],
|
||||||
|
[ int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)]; ],
|
||||||
|
[pgac_cv__types_compatible=yes],
|
||||||
|
[pgac_cv__types_compatible=no])])
|
||||||
|
if test x"$pgac_cv__types_compatible" = xyes ; then
|
||||||
|
AC_DEFINE(HAVE__BUILTIN_TYPES_COMPATIBLE_P, 1,
|
||||||
|
[Define to 1 if your compiler understands __builtin_types_compatible_p.])
|
||||||
|
fi])# PGAC_C_TYPES_COMPATIBLE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# PGAC_PROG_CC_CFLAGS_OPT
|
# PGAC_PROG_CC_CFLAGS_OPT
|
||||||
# -----------------------
|
# -----------------------
|
||||||
# Given a string, check if the compiler supports the string as a
|
# Given a string, check if the compiler supports the string as a
|
||||||
|
|
|
@ -15524,6 +15524,125 @@ cat >>confdefs.h <<\_ACEOF
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:$LINENO: checking for _Static_assert" >&5
|
||||||
|
$as_echo_n "checking for _Static_assert... " >&6; }
|
||||||
|
if test "${pgac_cv__static_assert+set}" = set; then
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
({ _Static_assert(1, "foo"); })
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||||
|
if { (ac_try="$ac_link"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
||||||
|
$as_echo "$ac_try_echo") >&5
|
||||||
|
(eval "$ac_link") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest$ac_exeext && {
|
||||||
|
test "$cross_compiling" = yes ||
|
||||||
|
$as_test_x conftest$ac_exeext
|
||||||
|
}; then
|
||||||
|
pgac_cv__static_assert=yes
|
||||||
|
else
|
||||||
|
$as_echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
pgac_cv__static_assert=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf conftest.dSYM
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:$LINENO: result: $pgac_cv__static_assert" >&5
|
||||||
|
$as_echo "$pgac_cv__static_assert" >&6; }
|
||||||
|
if test x"$pgac_cv__static_assert" = xyes ; then
|
||||||
|
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define HAVE__STATIC_ASSERT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:$LINENO: checking for __builtin_types_compatible_p" >&5
|
||||||
|
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
|
||||||
|
if test "${pgac_cv__types_compatible+set}" = set; then
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)];
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext
|
||||||
|
if { (ac_try="$ac_compile"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
||||||
|
$as_echo "$ac_try_echo") >&5
|
||||||
|
(eval "$ac_compile") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest.$ac_objext; then
|
||||||
|
pgac_cv__types_compatible=yes
|
||||||
|
else
|
||||||
|
$as_echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
pgac_cv__types_compatible=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:$LINENO: result: $pgac_cv__types_compatible" >&5
|
||||||
|
$as_echo "$pgac_cv__types_compatible" >&6; }
|
||||||
|
if test x"$pgac_cv__types_compatible" = xyes ; then
|
||||||
|
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
fi
|
fi
|
||||||
{ $as_echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
|
{ $as_echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
|
||||||
$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
|
$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
|
||||||
|
|
|
@ -1104,6 +1104,8 @@ AC_C_FLEXIBLE_ARRAY_MEMBER
|
||||||
PGAC_C_SIGNED
|
PGAC_C_SIGNED
|
||||||
AC_C_VOLATILE
|
AC_C_VOLATILE
|
||||||
PGAC_C_FUNCNAME_SUPPORT
|
PGAC_C_FUNCNAME_SUPPORT
|
||||||
|
PGAC_C_STATIC_ASSERT
|
||||||
|
PGAC_C_TYPES_COMPATIBLE
|
||||||
PGAC_STRUCT_TIMEZONE
|
PGAC_STRUCT_TIMEZONE
|
||||||
PGAC_UNION_SEMUN
|
PGAC_UNION_SEMUN
|
||||||
PGAC_STRUCT_SOCKADDR_UN
|
PGAC_STRUCT_SOCKADDR_UN
|
||||||
|
|
|
@ -689,6 +689,47 @@ typedef NameData *Name;
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros to support compile-time assertion checks, if the compiler has them.
|
||||||
|
*
|
||||||
|
* If the "condition" (a compile-time-constant expression) evaluates to false,
|
||||||
|
* throw a compile error using the "errmessage" (a string literal).
|
||||||
|
*
|
||||||
|
* gcc 4.6 and up supports _Static_assert(), but it has bizarre syntactic
|
||||||
|
* placement restrictions. These macros make it safe to use as a statement
|
||||||
|
* or in an expression, respectively.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE__STATIC_ASSERT
|
||||||
|
#define StaticAssertStmt(condition, errmessage) \
|
||||||
|
do { _Static_assert(condition, errmessage); } while(0)
|
||||||
|
#define StaticAssertExpr(condition, errmessage) \
|
||||||
|
({ StaticAssertStmt(condition, errmessage); true; })
|
||||||
|
#else /* !HAVE__STATIC_ASSERT */
|
||||||
|
#define StaticAssertStmt(condition, errmessage)
|
||||||
|
#define StaticAssertExpr(condition, errmessage) ((void) true)
|
||||||
|
#endif /* HAVE__STATIC_ASSERT */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compile-time checks that a variable (or expression) has the specified type.
|
||||||
|
*
|
||||||
|
* AssertVariableIsOfType() can be used as a statement.
|
||||||
|
* AssertVariableIsOfTypeMacro() is intended for use in macros, eg
|
||||||
|
* #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x))
|
||||||
|
*/
|
||||||
|
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
|
||||||
|
#define AssertVariableIsOfType(varname, typename) \
|
||||||
|
StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
|
||||||
|
CppAsString(varname) " does not have type " CppAsString(typename))
|
||||||
|
#define AssertVariableIsOfTypeMacro(varname, typename) \
|
||||||
|
StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
|
||||||
|
CppAsString(varname) " does not have type " CppAsString(typename))
|
||||||
|
#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
|
||||||
|
#define AssertVariableIsOfType(varname, typename)
|
||||||
|
#define AssertVariableIsOfTypeMacro(varname, typename) ((void) true)
|
||||||
|
#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* Section 7: random stuff
|
* Section 7: random stuff
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
|
|
|
@ -635,6 +635,12 @@
|
||||||
/* Define to 1 if you have the <winldap.h> header file. */
|
/* Define to 1 if you have the <winldap.h> header file. */
|
||||||
#undef HAVE_WINLDAP_H
|
#undef HAVE_WINLDAP_H
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
|
||||||
|
#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands _Static_assert. */
|
||||||
|
#undef HAVE__STATIC_ASSERT
|
||||||
|
|
||||||
/* Define to the appropriate snprintf format for 64-bit ints. */
|
/* Define to the appropriate snprintf format for 64-bit ints. */
|
||||||
#undef INT64_FORMAT
|
#undef INT64_FORMAT
|
||||||
|
|
||||||
|
|
|
@ -526,6 +526,12 @@
|
||||||
/* Define to 1 if you have the <winldap.h> header file. */
|
/* Define to 1 if you have the <winldap.h> header file. */
|
||||||
/* #undef HAVE_WINLDAP_H */
|
/* #undef HAVE_WINLDAP_H */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
|
||||||
|
/* #undef HAVE__BUILTIN_TYPES_COMPATIBLE_P */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands _Static_assert. */
|
||||||
|
/* #undef HAVE__STATIC_ASSERT */
|
||||||
|
|
||||||
/* Define to the appropriate snprintf format for 64-bit ints, if any. */
|
/* Define to the appropriate snprintf format for 64-bit ints, if any. */
|
||||||
#define INT64_FORMAT "%lld"
|
#define INT64_FORMAT "%lld"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue