]> thyrsus.com Git - intercal.git/commitdiff
Let configure check for the varargs/_Bool interaction
authorAlex Smith <ais523@bham.ac.uk>
Tue, 7 Sep 2010 19:54:44 +0000 (20:54 +0100)
committerAlex Smith <ais523@bham.ac.uk>
Tue, 7 Sep 2010 19:54:44 +0000 (20:54 +0100)
According to the C standard, passing _Bool via varargs is undefined
behaviour. This lets autoconf check to see whether it actually works,
and casts to int in the relevant location if it doesn't. (Recent gcc
will compile an attempt to access a boolean via varargs into an
illegal instruction.)

configure.ac
src/cesspool.c
src/feh2.c

index 948e331bf755b484ef930e6b8040c1287fc8c84c..4f2cf619b42a6edc3326d30fcf6b4e27584ffaa2 100644 (file)
@@ -53,6 +53,51 @@ AC_TYPE_SIZE_T
 AC_TYPE_UINT16_T
 AC_TYPE_UINT32_T
 
+# Some compilers (correctly according to the standard, but dubiously for
+# actual use in code) dislike mixing _Bool and varargs.
+if test "x$ac_cv_type__Bool" == "xyes"
+then
+AC_MSG_CHECKING([[whether booleans can be passed via varargs]])
+AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <stdlib.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+void test(int x, ...)
+#else
+#include <varargs.h>
+void test(va_alist) va_dcl
+#endif
+{
+  int y,z;
+  _Bool b;
+  va_list ap;
+#ifdef HAVE_STDARG_H
+  va_start(ap, x);
+  y = x;
+#else
+  va_start(ap);
+  y = va_arg(ap, int);
+#endif
+  b = va_arg(ap, _Bool);
+  z = va_arg(ap, int);
+  if(b && x != z) exit(2);
+  if(!b && x == z) exit(3);
+}
+]],[[
+_Bool match = (_Bool)1;
+_Bool nomatch = (_Bool) 0;
+test(12345,match,12345);
+test(23456,nomatch,1234);
+exit(0);
+]])],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
+AC_DEFINE([BOOL_VARARGS_BROKEN],[],dnl
+[Define if _Bool works but cannot be passed via varargs.])
+],[AC_MSG_RESULT([[unknown in a cross-compile, assuming no]])
+AC_DEFINE([BOOL_VARARGS_BROKEN],[],dnl
+[Define if _Bool works but cannot be passed via varargs.])
+])
+fi
+
 AC_MSG_CHECKING([[whether yyrestart() is needed]])
 # Write a lex program that will cause an error if yyrestart exists.
 echo '%%
index e1129b3fb3c581ca82c58c54e98d0076a98ba68a..eb55b1f70496e4577ef9a180905b58703bad33b0 100644 (file)
@@ -632,7 +632,11 @@ void ick_resize(va_alist) va_dcl
   type = va_arg(ap, unsigned int);
 #endif
   a = va_arg(ap, ick_array*);
+#ifdef BOOL_VARARGS_BROKEN
+  forget = (bool)va_arg(ap, int);
+#else
   forget = va_arg(ap, bool);
+#endif
 
   /* AIS: a->dims is no longer initialised. So initialise it here if
      it isn't already initialised, with an annotation to explain that
index 99b4be52d8703c739ed62bdd8a4eb5250cf33e83..3eb714841acf856c227591bee574e4181c07703f 100644 (file)
@@ -2099,8 +2099,13 @@ void emit(tuple *tn, FILE *fp)
          dim++;
        (void) fprintf(fp, "\t""ick_resize(");
        prvar(np->lval, fp, 1);
+#ifdef BOOL_VARARGS_BROKEN
+       (void) fprintf(fp, ", (int)%s[%lu]", nameof(np->lval->opcode, forgetbits),
+                      np->lval->constant);
+#else
        (void) fprintf(fp, ", %s[%lu]", nameof(np->lval->opcode, forgetbits),
                       np->lval->constant);
+#endif
        (void) fprintf(fp, ", %d", dim);
        for (sp = np->rval; sp; sp = sp->rval) {
          (void) fprintf(fp, ", (size_t)");