0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.0.1736: check for C99 features is incomplete

Problem:    Check for C99 features is incomplete.
Solution:   Use AC_PROG_CC_C99 and when C99 isn't fully supported check the
            features we need. (James McCoy, closes #2820)
This commit is contained in:
Bram Moolenaar 2018-04-19 20:39:41 +02:00
parent 285e335869
commit 226400830b
3 changed files with 342 additions and 82 deletions

372
src/auto/configure vendored
View File

@ -3454,81 +3454,167 @@ 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_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } $as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
if ${ac_cv_prog_cc_c89+:} false; then : if ${ac_cv_prog_cc_c99+:} false; then :
$as_echo_n "(cached) " >&6 $as_echo_n "(cached) " >&6
else else
ac_cv_prog_cc_c89=no ac_cv_prog_cc_c99=no
ac_save_CC=$CC ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdio.h> #include <stdio.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ // Check varargs macros. These examples are taken from C99 6.10.3.5.
struct buf { int x; }; #define debug(...) fprintf (stderr, __VA_ARGS__)
FILE * (*rcsopen) (struct buf *, struct stat *, int); #define showlist(...) puts (#__VA_ARGS__)
static char *e (p, i) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
char **p; static void
int i; test_varargs_macros (void)
{ {
return p[i]; int x = 1234;
} int y = 5678;
static char *f (char * (*g) (char **, int), char **p, ...) debug ("Flag");
{ debug ("X = %d\n", x);
char *s; showlist (The first, second, and third items.);
va_list v; report (x>y, "x is %d but y is %d", x, y);
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
} }
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has // Check long long types.
function prototypes and stuff, but not '\xHH' hex character constants. #define BIG64 18446744073709551615ull
These don't provoke an error unfortunately, instead are silently treated #define BIG32 4294967295ul
as 'x'. The following induces an error, until -std is added to get #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an #if !BIG_OK
array size at least. It's necessary to write '\x00'==0 to get something your preprocessor is broken;
that's true only with -std. */ #endif
int osf4_cc_array ['\x00' == 0 ? 1 : -1]; #if BIG_OK
#else
your preprocessor is broken;
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;
/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters struct incomplete_array
inside strings and character constants. */ {
#define FOO(x) 'x' int datasize;
int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; double data[];
};
struct named_init {
int number;
const wchar_t *name;
double average;
};
typedef const char *ccp;
static inline int
test_restrict (ccp restrict text)
{
// See if C++-style comments work.
// Iterate through items via the restricted pointer.
// Also check for declarations in for loops.
for (unsigned int i = 0; *(text+i) != '\0'; ++i)
continue;
return 0;
}
// Check varargs and va_copy.
static void
test_varargs (const char *format, ...)
{
va_list args;
va_start (args, format);
va_list args_copy;
va_copy (args_copy, args);
const char *str;
int number;
float fnumber;
while (*format)
{
switch (*format++)
{
case 's': // string
str = va_arg (args_copy, const char *);
break;
case 'd': // int
number = va_arg (args_copy, int);
break;
case 'f': // float
fnumber = va_arg (args_copy, double);
break;
default:
break;
}
}
va_end (args_copy);
va_end (args);
}
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int int
main () main ()
{ {
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
// Check bool.
_Bool success = false;
// Check restrict.
if (test_restrict ("String literal") == 0)
success = true;
char *restrict newvar = "Another string";
// Check varargs.
test_varargs ("s, d' f .", "string", 65, 34.234);
test_varargs_macros ();
// Check flexible array members.
struct incomplete_array *ia =
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
ia->datasize = 10;
for (int i = 0; i < ia->datasize; ++i)
ia->data[i] = i * 1.234;
// Check named initializers.
struct named_init ni = {
.number = 34,
.name = L"Test wide string",
.average = 543.34343,
};
ni.number = 58;
int dynamic_array[ni.number];
dynamic_array[ni.number - 1] = 543;
// work around unused variable warnings
return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
|| dynamic_array[ni.number - 1] != 543);
; ;
return 0; return 0;
} }
_ACEOF _ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do do
CC="$ac_save_CC $ac_arg" CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then : if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c89=$ac_arg ac_cv_prog_cc_c99=$ac_arg
fi fi
rm -f core conftest.err conftest.$ac_objext rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c89" != "xno" && break test "x$ac_cv_prog_cc_c99" != "xno" && break
done done
rm -f conftest.$ac_ext rm -f conftest.$ac_ext
CC=$ac_save_CC CC=$ac_save_CC
fi fi
# AC_CACHE_VAL # AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in case "x$ac_cv_prog_cc_c99" in
x) x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;; $as_echo "none needed" >&6; } ;;
@ -3536,11 +3622,11 @@ $as_echo "none needed" >&6; } ;;
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;; $as_echo "unsupported" >&6; } ;;
*) *)
CC="$CC $ac_cv_prog_cc_c89" CC="$CC $ac_cv_prog_cc_c99"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; $as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
esac esac
if test "x$ac_cv_prog_cc_c89" != xno; then : if test "x$ac_cv_prog_cc_c99" != xno; then :
fi fi
@ -4179,35 +4265,193 @@ $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
fi fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler can handle Vim code" >&5 if test x"$ac_cv_prog_cc_c99" != xno; then
$as_echo_n "checking if the compiler can handle Vim code... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
$as_echo_n "checking for unsigned long long int... " >&6; }
if ${ac_cv_type_unsigned_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_type_unsigned_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
#include <stdio.h>
/* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */
/* Test literals. */
long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)];
int i = 63;
int
main ()
{
/* Test availability of runtime routines for shift and division. */
long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull));
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
else
ac_cv_type_unsigned_long_long_int=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; }
if test $ac_cv_type_unsigned_long_long_int = yes; then
$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5
$as_echo_n "checking for long long int... " >&6; }
if ${ac_cv_type_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_type_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
if test $ac_cv_type_long_long_int = yes; then
if test "$cross_compiling" = yes; then :
:
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
#ifndef LLONG_MAX
# define HALF \
(1LL << (sizeof (long long int) * CHAR_BIT - 2))
# define LLONG_MAX (HALF - 1 + HALF)
#endif
int
main ()
{
long long int n = 1;
int i;
for (i = 0; ; i++)
{
long long int m = n << i;
if (m >> i != n)
return 1;
if (LLONG_MAX / 2 < m)
break;
}
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
else
ac_cv_type_long_long_int=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5
$as_echo "$ac_cv_type_long_long_int" >&6; }
if test $ac_cv_type_long_long_int = yes; then
$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h
fi
if test "$ac_cv_type_long_long_int" = no; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Compiler does not support long long int
See \`config.log' for more details" "$LINENO" 5; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler supports trailing commas" >&5
$as_echo_n "checking if the compiler supports trailing commas... " >&6; }
trailing_commas=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int int
main () main ()
{ {
enum { enum {
one, // one comment one,
two, // two comments };
three, // three comments
};
long long int a = 1;
long long unsigned b = 2;
printf("a %lld and a %llu", a, b);
; ;
return 0; return 0;
} }
_ACEOF _ACEOF
if ac_fn_c_try_compile "$LINENO"; then : if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; } $as_echo "yes" >&6; }; trailing_commas=yes
else else
as_fn_error $? "compiler does not work properly - see auto/config.log" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "$trailing_commas" = no; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Compiler does not support trailing comma in enum
See \`config.log' for more details" "$LINENO" 5; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler supports C++ comments" >&5
$as_echo_n "checking if the compiler supports C++ comments... " >&6; }
slash_comments=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
// C++ comments?
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }; slash_comments=yes
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "$slash_comments" = no; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Compiler does not support C++ comments
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-fail-if-missing argument" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-fail-if-missing argument" >&5

View File

@ -11,7 +11,7 @@ AC_DEFINE(UNIX)
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
dnl Checks for programs. dnl Checks for programs.
AC_PROG_CC_C89 dnl required by almost everything AC_PROG_CC_C99 dnl required by almost everything
AC_PROG_CPP dnl required by header file checks AC_PROG_CPP dnl required by header file checks
AC_PROGRAM_EGREP dnl required by AC_EGREP_CPP AC_PROGRAM_EGREP dnl required by AC_EGREP_CPP
AC_PROG_FGREP dnl finds working grep -F AC_PROG_FGREP dnl finds working grep -F
@ -30,23 +30,37 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
dnl Check that the C99 features that Vim uses are supported: dnl Check that the C99 features that Vim uses are supported:
dnl - // commands if test x"$ac_cv_prog_cc_c99" != xno; then
dnl - comma after last enum item dnl If the compiler doesn't explicitly support C99, then check
dnl - "long long int" and "long long unsigned" dnl for the specific features Vim uses
dnl - flexible array member
AC_MSG_CHECKING(if the compiler can handle Vim code) AC_TYPE_LONG_LONG_INT
AC_TRY_COMPILE([#include <stdio.h>], [ if test "$ac_cv_type_long_long_int" = no; then
enum { AC_MSG_FAILURE([Compiler does not support long long int])
one, // one comment fi
two, // two comments
three, // three comments AC_MSG_CHECKING([if the compiler supports trailing commas])
}; trailing_commas=no
long long int a = 1; AC_TRY_COMPILE([], [
long long unsigned b = 2; enum {
printf("a %lld and a %llu", a, b); one,
], };],
AC_MSG_RESULT(yes), [AC_MSG_RESULT(yes); trailing_commas=yes],
AC_MSG_ERROR([compiler does not work properly - see auto/config.log])) [AC_MSG_RESULT(no)])
if test "$trailing_commas" = no; then
AC_MSG_FAILURE([Compiler does not support trailing comma in enum])
fi
AC_MSG_CHECKING([if the compiler supports C++ comments])
slash_comments=no
AC_TRY_COMPILE([],
[// C++ comments?],
[AC_MSG_RESULT(yes); slash_comments=yes],
[AC_MSG_RESULT(no)])
if test "$slash_comments" = no; then
AC_MSG_FAILURE([Compiler does not support C++ comments])
fi
fi
dnl Check for the flag that fails if stuff are missing. dnl Check for the flag that fails if stuff are missing.

View File

@ -762,6 +762,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1736,
/**/ /**/
1735, 1735,
/**/ /**/