Skip to content

Commit da25330

Browse files
petereCommitfest Bot
authored andcommitted
Raise C requirement to C11
This changes configure and meson.build to require at least C11, instead of the previous C99. The installation documentation is updated accordingly. configure.ac previously used AC_PROG_CC_C99 to activate C99. But there is no AC_PROG_CC_C11 in Autoconf 2.69, because it's too old. (Also, post-2.69, the AC_PROG_CC_Cnn macros were deprecated and AC_PROG_CC activates the last supported C mode.) We could update the required Autoconf version, but that might be a separate project that no one wants to undertake at the moment. Instead, we open-code the test for C11 using some inspiration from later Autoconf versions. But instead of writing an elaborate test program, we keep it simple and just check __STDC_VERSION__, which should be good enough in practice. In meson.build, we update the existing C99 test to C11, but again we just check for __STDC_VERSION__. This also removes the separate option for the conforming preprocessor on MSVC, added by commit 8fd9bb1, since that is activated automatically in C11 mode. Note, we don't use the "official" way to set the C standard in Meson using the c_std project option, because that is impossible to use correctly (see <mesonbuild/meson#14717>).
1 parent 878656d commit da25330

File tree

5 files changed

+83
-228
lines changed

5 files changed

+83
-228
lines changed

configure

Lines changed: 31 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -4475,190 +4475,49 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
44754475
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
44764476
ac_compiler_gnu=$ac_cv_c_compiler_gnu
44774477

4478-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
4479-
$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
4480-
if ${ac_cv_prog_cc_c99+:} false; then :
4478+
4479+
# Detect option needed for C11
4480+
# loosely modeled after code in later Autoconf versions
4481+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C11" >&5
4482+
$as_echo_n "checking for $CC option to accept ISO C11... " >&6; }
4483+
4484+
if ${pgac_cv_prog_cc_c11+:} false; then :
44814485
$as_echo_n "(cached) " >&6
44824486
else
4483-
ac_cv_prog_cc_c99=no
4484-
ac_save_CC=$CC
4485-
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
4487+
pgac_cv_prog_cc_c11=no
4488+
pgac_save_CC=$CC
4489+
for pgac_arg in '' '-std=gnu11' '-std=c11'; do
4490+
CC="$pgac_save_CC $pgac_arg"
4491+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
44864492
/* end confdefs.h. */
4487-
#include <stdarg.h>
4488-
#include <stdbool.h>
4489-
#include <stdlib.h>
4490-
#include <wchar.h>
4491-
#include <stdio.h>
4492-
4493-
// Check varargs macros. These examples are taken from C99 6.10.3.5.
4494-
#define debug(...) fprintf (stderr, __VA_ARGS__)
4495-
#define showlist(...) puts (#__VA_ARGS__)
4496-
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
4497-
static void
4498-
test_varargs_macros (void)
4499-
{
4500-
int x = 1234;
4501-
int y = 5678;
4502-
debug ("Flag");
4503-
debug ("X = %d\n", x);
4504-
showlist (The first, second, and third items.);
4505-
report (x>y, "x is %d but y is %d", x, y);
4506-
}
4507-
4508-
// Check long long types.
4509-
#define BIG64 18446744073709551615ull
4510-
#define BIG32 4294967295ul
4511-
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
4512-
#if !BIG_OK
4513-
your preprocessor is broken;
4514-
#endif
4515-
#if BIG_OK
4516-
#else
4517-
your preprocessor is broken;
4493+
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
4494+
# error "Compiler does not advertise C11 conformance"
45184495
#endif
4519-
static long long int bignum = -9223372036854775807LL;
4520-
static unsigned long long int ubignum = BIG64;
4521-
4522-
struct incomplete_array
4523-
{
4524-
int datasize;
4525-
double data[];
4526-
};
4527-
4528-
struct named_init {
4529-
int number;
4530-
const wchar_t *name;
4531-
double average;
4532-
};
4533-
4534-
typedef const char *ccp;
4535-
4536-
static inline int
4537-
test_restrict (ccp restrict text)
4538-
{
4539-
// See if C++-style comments work.
4540-
// Iterate through items via the restricted pointer.
4541-
// Also check for declarations in for loops.
4542-
for (unsigned int i = 0; *(text+i) != '\0'; ++i)
4543-
continue;
4544-
return 0;
4545-
}
4546-
4547-
// Check varargs and va_copy.
4548-
static void
4549-
test_varargs (const char *format, ...)
4550-
{
4551-
va_list args;
4552-
va_start (args, format);
4553-
va_list args_copy;
4554-
va_copy (args_copy, args);
4555-
4556-
const char *str;
4557-
int number;
4558-
float fnumber;
4559-
4560-
while (*format)
4561-
{
4562-
switch (*format++)
4563-
{
4564-
case 's': // string
4565-
str = va_arg (args_copy, const char *);
4566-
break;
4567-
case 'd': // int
4568-
number = va_arg (args_copy, int);
4569-
break;
4570-
case 'f': // float
4571-
fnumber = va_arg (args_copy, double);
4572-
break;
4573-
default:
4574-
break;
4575-
}
4576-
}
4577-
va_end (args_copy);
4578-
va_end (args);
4579-
}
4580-
4581-
int
4582-
main ()
4583-
{
4584-
4585-
// Check bool.
4586-
_Bool success = false;
4587-
4588-
// Check restrict.
4589-
if (test_restrict ("String literal") == 0)
4590-
success = true;
4591-
char *restrict newvar = "Another string";
4592-
4593-
// Check varargs.
4594-
test_varargs ("s, d' f .", "string", 65, 34.234);
4595-
test_varargs_macros ();
4596-
4597-
// Check flexible array members.
4598-
struct incomplete_array *ia =
4599-
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
4600-
ia->datasize = 10;
4601-
for (int i = 0; i < ia->datasize; ++i)
4602-
ia->data[i] = i * 1.234;
4603-
4604-
// Check named initializers.
4605-
struct named_init ni = {
4606-
.number = 34,
4607-
.name = L"Test wide string",
4608-
.average = 543.34343,
4609-
};
4610-
4611-
ni.number = 58;
4612-
4613-
int dynamic_array[ni.number];
4614-
dynamic_array[ni.number - 1] = 543;
4615-
4616-
// work around unused variable warnings
4617-
return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
4618-
|| dynamic_array[ni.number - 1] != 543);
4619-
4620-
;
4621-
return 0;
4622-
}
46234496
_ACEOF
4624-
for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
4625-
do
4626-
CC="$ac_save_CC $ac_arg"
4627-
if ac_fn_c_try_compile "$LINENO"; then :
4628-
ac_cv_prog_cc_c99=$ac_arg
4497+
if ac_fn_c_try_compile "$LINENO"; then :
4498+
pgac_cv_prog_cc_c11=$pgac_arg
46294499
fi
4630-
rm -f core conftest.err conftest.$ac_objext
4631-
test "x$ac_cv_prog_cc_c99" != "xno" && break
4500+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
4501+
test x"$pgac_cv_prog_cc_c11" != x"no" && break
46324502
done
4633-
rm -f conftest.$ac_ext
4634-
CC=$ac_save_CC
4635-
4636-
fi
4637-
# AC_CACHE_VAL
4638-
case "x$ac_cv_prog_cc_c99" in
4639-
x)
4640-
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
4641-
$as_echo "none needed" >&6; } ;;
4642-
xno)
4643-
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
4644-
$as_echo "unsupported" >&6; } ;;
4645-
*)
4646-
CC="$CC $ac_cv_prog_cc_c99"
4647-
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
4648-
$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
4649-
esac
4650-
if test "x$ac_cv_prog_cc_c99" != xno; then :
4651-
4503+
CC=$pgac_save_CC
46524504
fi
46534505

46544506

4655-
4656-
# Error out if the compiler does not support C99, as the codebase
4657-
# relies on that.
4658-
if test "$ac_cv_prog_cc_c99" = no; then
4659-
as_fn_error $? "C compiler \"$CC\" does not support C99" "$LINENO" 5
4507+
if test x"$pgac_cv_prog_cc_c11" = x"no"; then
4508+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
4509+
$as_echo "unsupported" >&6; }
4510+
as_fn_error $? "C compiler \"$CC\" does not support C11" "$LINENO" 5
4511+
elif test x"$pgac_cv_prog_cc_c11" = x""; then
4512+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
4513+
$as_echo "none needed" >&6; }
4514+
else
4515+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_cc_c11" >&5
4516+
$as_echo "$pgac_cv_prog_cc_c11" >&6; }
4517+
CC="$CC $pgac_cv_prog_cc_c11"
46604518
fi
46614519

4520+
46624521
ac_ext=cpp
46634522
ac_cpp='$CXXCPP $CPPFLAGS'
46644523
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4920,7 +4779,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
49204779
# Check if it's Intel's compiler, which (usually) pretends to be gcc,
49214780
# but has idiosyncrasies of its own. We assume icc will define
49224781
# __INTEL_COMPILER regardless of CFLAGS.
4923-
49244782
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
49254783
/* end confdefs.h. */
49264784

configure.ac

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,14 +364,33 @@ pgac_cc_list="gcc cc"
364364
pgac_cxx_list="g++ c++"
365365

366366
AC_PROG_CC([$pgac_cc_list])
367-
AC_PROG_CC_C99()
368367

369-
# Error out if the compiler does not support C99, as the codebase
370-
# relies on that.
371-
if test "$ac_cv_prog_cc_c99" = no; then
372-
AC_MSG_ERROR([C compiler "$CC" does not support C99])
368+
# Detect option needed for C11
369+
# loosely modeled after code in later Autoconf versions
370+
AC_MSG_CHECKING([for $CC option to accept ISO C11])
371+
AC_CACHE_VAL([pgac_cv_prog_cc_c11],
372+
[pgac_cv_prog_cc_c11=no
373+
pgac_save_CC=$CC
374+
for pgac_arg in '' '-std=gnu11' '-std=c11'; do
375+
CC="$pgac_save_CC $pgac_arg"
376+
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
377+
# error "Compiler does not advertise C11 conformance"
378+
#endif]])], [[pgac_cv_prog_cc_c11=$pgac_arg]])
379+
test x"$pgac_cv_prog_cc_c11" != x"no" && break
380+
done
381+
CC=$pgac_save_CC])
382+
383+
if test x"$pgac_cv_prog_cc_c11" = x"no"; then
384+
AC_MSG_RESULT([unsupported])
385+
AC_MSG_ERROR([C compiler "$CC" does not support C11])
386+
elif test x"$pgac_cv_prog_cc_c11" = x""; then
387+
AC_MSG_RESULT([none needed])
388+
else
389+
AC_MSG_RESULT([$pgac_cv_prog_cc_c11])
390+
CC="$CC $pgac_cv_prog_cc_c11"
373391
fi
374392

393+
375394
AC_PROG_CXX([$pgac_cxx_list])
376395

377396
# Check if it's Intel's compiler, which (usually) pretends to be gcc,

doc/src/sgml/installation.sgml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@
7171

7272
<listitem>
7373
<para>
74-
You need an <acronym>ISO</acronym>/<acronym>ANSI</acronym> C compiler (at least
75-
C99-compliant). Recent
76-
versions of <productname>GCC</productname> are recommended, but
77-
<productname>PostgreSQL</productname> is known to build using a wide variety
74+
You need a C compiler that supports at least C11. Recent versions of
75+
<productname>GCC</productname> are recommended, but
76+
<productname>PostgreSQL</productname> is known to build using a variety
7877
of compilers from different vendors.
7978
</para>
8079
</listitem>

doc/src/sgml/sources.sgml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -907,12 +907,12 @@ BETTER: unrecognized node type: 42
907907
<title>C Standard</title>
908908
<para>
909909
Code in <productname>PostgreSQL</productname> should only rely on language
910-
features available in the C99 standard. That means a conforming
911-
C99 compiler has to be able to compile postgres, at least aside
910+
features available in the C11 standard. That means a conforming
911+
C11 compiler has to be able to compile postgres, at least aside
912912
from a few platform dependent pieces.
913913
</para>
914914
<para>
915-
A few features included in the C99 standard are, at this time, not
915+
A few features included in the C11 standard are, at this time, not
916916
permitted to be used in core <productname>PostgreSQL</productname>
917917
code. This currently includes variable length arrays, intermingled
918918
declarations and code, <literal>//</literal> comments, universal
@@ -924,13 +924,11 @@ BETTER: unrecognized node type: 42
924924
features can be used, if a fallback is provided.
925925
</para>
926926
<para>
927-
For example <literal>_Static_assert()</literal> and
927+
For example <literal>typeof()</literal> and
928928
<literal>__builtin_constant_p</literal> are currently used, even though
929929
they are from newer revisions of the C standard and a
930930
<productname>GCC</productname> extension respectively. If not available
931-
we respectively fall back to using a C99 compatible replacement that
932-
performs the same checks, but emits rather cryptic messages and do not
933-
use <literal>__builtin_constant_p</literal>.
931+
we do not use them.
934932
</para>
935933
</simplesect>
936934

meson.build

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,6 @@ elif host_system == 'windows'
280280
# define before including <time.h> for getting localtime_r() etc. on MinGW
281281
cppflags += '-D_POSIX_C_SOURCE'
282282
endif
283-
if cc.get_id() == 'msvc'
284-
# required for VA_ARGS_NARGS() in c.h; requires VS 2019
285-
cppflags += '/Zc:preprocessor'
286-
endif
287283

288284
export_file_format = 'win'
289285
export_file_suffix = 'def'
@@ -550,44 +546,29 @@ dir_doc_extension = dir_doc / 'extension'
550546
# used, they need to be added to test_c_args as well.
551547
###############################################################
552548

553-
# Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
554-
# unnecessarily, because we optionally rely on newer features.
555-
c99_test = '''
556-
#include <stdbool.h>
557-
#include <complex.h>
558-
#include <tgmath.h>
559-
#include <inttypes.h>
560-
561-
struct named_init_test {
562-
int a;
563-
int b;
564-
};
565-
566-
extern void structfunc(struct named_init_test);
567-
568-
int main(int argc, char **argv)
569-
{
570-
struct named_init_test nit = {
571-
.a = 3,
572-
.b = 5,
573-
};
574-
575-
for (int loop_var = 0; loop_var < 3; loop_var++)
576-
{
577-
nit.a += nit.b;
578-
}
579-
580-
structfunc((struct named_init_test){1, 0});
581-
582-
return nit.a != 0;
583-
}
549+
# Do we need an option to enable C11?
550+
c11_test = '''
551+
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
552+
# error "Compiler does not advertise C11 conformance"
553+
#endif
584554
'''
585555

586-
if not cc.compiles(c99_test, name: 'c99')
587-
if cc.compiles(c99_test, name: 'c99 with -std=c99', args: ['-std=c99'])
588-
cflags += '-std=c99'
556+
if not cc.compiles(c11_test, name: 'C11')
557+
c11_ok = false
558+
if cc.get_id() == 'msvc'
559+
c11_test_args = ['/std:c11']
589560
else
590-
error('C compiler does not support C99')
561+
c11_test_args = ['-std=gnu11', '-std=c11']
562+
endif
563+
foreach arg : c11_test_args
564+
if cc.compiles(c11_test, name: 'C11 with @0@'.format(arg), args: [arg])
565+
c11_ok = true
566+
cflags += arg
567+
break
568+
endif
569+
endforeach
570+
if not c11_ok
571+
error('C compiler does not support C11')
591572
endif
592573
endif
593574

0 commit comments

Comments
 (0)