Re: Making MSVC/clang-cl succeed AC_PROG_CC C11 discovery

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 23, 2024 at 09:07:49PM -0300, Antonin Décimo wrote:
> I'm hacking on the Autoconf scripts for the OCaml compiler [1]. I'm
> trying to make them more useful when compiling with the dreaded MSVC.

Thanks for tackling this!

> MSVC has supported C11 and C17 since September 2020 [2]. The options
> to enable support are `/std:c11` and `/std:c17`. There's an
> alternative syntax, `-std:c11` and `-std:c17` (dash instead of slash).
> 
>     diff --git a/lib/autoconf/c.m4 b/lib/autoconf/c.m4
>     index d8eab7bb..01d4cfa6 100644
>     --- a/lib/autoconf/c.m4
>     +++ b/lib/autoconf/c.m4
>     @@ -1553,6 +1553,7 @@ m4_define([_AC_C_C99_OPTIONS], [
>      # shell quotes around the group.
>      #
>      # GCC, Clang    -std=gnu11
>     +# MSVC          -std:c11
>      #
>      # For IBM XL C for AIX V16.1 or later, '-std=gnu11' should work if
>      # the user configured with CC='xlclang'.  Otherwise, do not try
>     @@ -1562,6 +1563,7 @@ m4_define([_AC_C_C99_OPTIONS], [
>      # _Noreturn, which is a win.
>      m4_define([_AC_C_C11_OPTIONS], [
>          -std=gnu11
>     +    -std:c11
>      ])

This change looks correct to me in isolation, and I concur with using
the dash-prefix form for the reasons you stated in your other message.

> MSVC doesn't enable the `__STDC__` macro by default, it needs a
> `/Zc:__STDC__` flag [3]. This is done to prevent compatibility issues [4].
...
> MSVC fails this check. I'm tempted to add the `/Zc:__STDC__` flag to
> `_AC_C_C11_OPTIONS`, however its doc reads:
> 
> > Do not try "strictly conforming" modes (e.g. gcc's -std=c11); they
> > break some systems' header files.
...
> Should both `/std:c11 /Zc:__STDC__` be added to `_AC_C_C11_OPTIONS` to
> support MSVC? Should Autoconf remove the `__STDC__` check or check for
> MSVC at this stage?

This is a hard one.

I haven't done much programming for Windows at all, but I have had to work
with other systems that had more-or-less ISO-C89-conformant compilers and
C runtimes but didn't define __STDC__, for more or less the same reason
Microsoft isn't defining it -- they didn't want to claim conformance
outside of a "strict conformance" mode that caused more problems than
it solved.  In the 1990s and early 2000s, it was very common to see
#ifdef __STDC__ or #if __STDC__ in application code, for example using it
to decide whether to use prototyped or old-style function definitions.
That code would, in the worst case, fail to compile on the systems I'm
thinking of, because *both* modes were wrong -- with __STDC__ not defined,
they would use the "K&R compiler" side of the ifdefs and do things like
preprocessor token concatenation the wrong way; with __STDC__ defined,
the C library was in "strict" mode and missing important declarations
from the headers.

Nowadays, preprocessor conditionals on __STDC__ are less common, but I
am still worried that both possibilities are wrong: with /Zc:__STDC__
Microsoft's compilers will make <fcntl.h> not declare open(), breaking
application code; without it, application code may assume that it's
dealing with a "K&R" compiler.

I think we need input here from an expert on low-level C programming
and portability issues specifically for Windows.  If anyone reading
this has those qualifications, please speak up.  I will try to find
someone through other means if nobody speaks up in a week or two.

(The comment about "strictly conforming" modes breaking system headers
was motivated by a related problem: on some systems, the code *inside*
important headers like <netinet/in.h> will throw compile errors if you
feed it to GCC in -std=cXX mode, because it's never been tested that
way.  However, that comment is definitely *relevant*.  If the preprocessor
macro under discussion was anything but __STDC__ or __STDC_VERSION__ I
would say "no, don't use that option here" without hesitation, but...)

(Can you check if there's maybe some way to make the UCRT declare
POSIX functions like open(), without a leading underscore, *even if*
__STDC__ is defined?  Another macro that you define, maybe?)

> The second problem is that MSVC has no support for Variable-Length
> Arrays (VLA) [5]. There is however a test for VLAs in
> `_AC_C_C99_TEST_MAIN`. C11 has introduced in _6.10.8.3 Conditional
> feature macros_:
> 
> > `__STDC_NO_VLA__` The integer constant `1`, intended to indicate
> > that the implementation does not support variable length arrays or
> > variably modified types.
> 
> However the VLA test is included as-is in the C11 main program, but
> C11 made that feature optional. MSVC correctly defines the
> `__STDC_NO_VLA__` macro, but fails the Autoconf test. This is clearly
> an Autoconf bug, but the fix isn't clear.

I think what we should do here is fold AC_C_VARARRAYS into AC_PROG_CC.
Take the test for VLAs completely out of _AC_C_C99_TEST_MAIN, but
unconditionally *run* a test for VLAs as part of AC_PROG_CC.  If that
test fails, and __STDC_NO_VLA__ was not defined by the compiler,
then AC_DEFINE([__STDC_NO_VLA__], 1) and set a cache variable.
Mark AC_C_VARARRAYS as obsolete (i.e. AU_DEFUN it) and have it
just check the cache variable and AC_DEFINE(HAVE_C_VARARRAYS),
with post-autoupdate diagnostics telling the reader to replace
HAVE_C_VARARRAYS with !__STDC_NO_VLA__ and then remove the
compatibility code.  Do you know how to do all of that?  I can
do it (not for another couple of weeks) if it sounds too daunting,
but I will need you to test it for me as I don't have convenient
access to a compiler that doesn't support VLAs.

zw




[Index of Archives]     [GCC Help]     [Kernel Discussion]     [RPM Discussion]     [Red Hat Development]     [Yosemite News]     [Linux USB]     [Samba]

  Powered by Linux