This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Teach Configure and cflags.SH about C99 master
authorH.Merijn Brand <perl5@tux.freedom.nl>
Fri, 29 Oct 2021 15:35:45 +0000 (17:35 +0200)
committerH.Merijn Brand <perl5@tux.freedom.nl>
Fri, 29 Oct 2021 15:35:45 +0000 (17:35 +0200)
Test declarations after statement in Configure's C99 probe code

Probe to see whether we need -std=gnu99 or -std=c99 to get C99 code to
compile. In cflags.SH, remove code that added gcc warning flags that were
compatible with C89 but are not compatible with C99.

Also ensure that the relevant failure error message is output even with
Configure's -s flag, as we shouldn't stay silent for a message that causes
Configure default to aborting.

With these changes, Configure will fail the C99 probe test if passed
-Accflags="-Werror=declaration-after-statement" or
-Accflags="-Werror=long-long"

Backport of 0c7be120244c1a6aae9b1ae30124265bcb8184da
        and d34aca5e9e57e3f0b5d25d451759237b40647664

U/perl/gccvers.U

index 21c96ef..327dbf0 100644 (file)
@@ -28,6 +28,8 @@
 ?S:.
 ?D:gccversion=''
 ?D:gccansipedantic=''
+?T:c99_for
+?T:flag
 ?T:gccshortvers
 ?T:incdir
 ?T:warn
@@ -148,3 +150,58 @@ case "$gccversion" in
     esac
 esac
 
+# Really old versions of gcc default to C89 and will error for this code.
+# See if the compiler (gcc or otherwise) needs a flag to compile C99 code
+# Initialisations in for loops seem to be the particular problem
+# (Does this syntax conflict with something else that was valid C89?)
+# We also add a declaration after a statement to detect whether the compiler
+# (or the user supplied -Accflags) consider such declarations to be errors.
+# This causes 'Configure with -Accflags="-Werror=declaration-after-statement"'
+# to fail hard and early.
+#
+# Annoyingly -std=c99 will cause gcc to tell glibc not to define prototypes for
+# syscall, drand48 etc when including <unistd.h>, which messes up our build.
+# I guess we *could* loop round trying -std=c99 first with checks both for the
+# prototype found and the code compiling (because -std=gnu99 might do other
+# things we don't want, particularly on non-GCC compilers) but
+# 1) We would need to check for the prototype first (without any flags)
+# 2) We would still end up with most Linux systems either being -std=gnu99
+#    or "" (no flag), and so both common options would not rigorously check our
+#    portability to other platforms.
+# So it doesn't seem worth the complexity and chance of different failure.
+$cat >try.c <<'EOCP'
+int main(int argc, char **argv) {
+    argc = argc + 1;
+    /* This is deliberately a declaration after a statement. */
+    unsigned long long count = 0;
+    for (char **p = argv; *p; ++p) {
+        ++count;
+    }
+    return count == 1 ? 0 : argc;
+}
+EOCP
+c99_for=no
+for flag in '' '-std=gnu99' '-std=c99'; do
+    if $cc -o try $flag $ccflags $ldflags try.c 2>/dev/null && ./try; then
+        c99_for="$flag"
+        break;
+    fi
+done
+case "$c99_for" in
+'') echo "Your C compiler doesn't need any special flags to compile C99 code"
+    ;;
+no) echo >&4 "Your C compiler doesn't seem to be able to compile C99 code"
+    rp='Do you really want to continue?'
+    dflt='n'
+    . ./myread
+    case "$ans" in
+       [yY])   echo >&4 "Okay, continuing."    ;;
+       *)      exit 1                          ;;
+    esac
+    ;;
+*)  echo "Your C compiler needs $c99_for to compile C99 code"
+    ccflags="$c99_for $ccflags"
+    ;;
+esac
+$rm -f try try.*
+