Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aid compatibility with older Microsoft C compilers #1176

Merged
merged 4 commits into from
Feb 13, 2020

Conversation

dra27
Copy link
Member

@dra27 dra27 commented May 18, 2017

In other projects, it is useful to be able to tell GCC to run with --std=c89 in order to write C code which is compatible with Microsoft's C compiler, but this disables the inline keyword, as that's officially only part of C99.

This GPR proposes altering the headers to use GCC's __inline__ keyword, which is always available in GCC, and introduces a test in configure which adds a definition for __inline__ if the C compiler does not support it.

I think that this "trick" using --std=c89 to force compatibility with MSVC is a safe thing to do, but I'd very much appreciate input from someone who really gets the differences in semantics between -fgnu89-inline (which is also enabled by using --std=c89) and C99 inline.

@dra27 dra27 force-pushed the c89_headers branch 2 times, most recently from 1e0f9c0 to 643752d Compare May 18, 2017 12:41
@oandrieu
Copy link
Contributor

I'm confused, why don't you simply compile you C code with MSVC to check that it's compatible ?

@dra27
Copy link
Member Author

dra27 commented May 18, 2017

I'll look into what I've done incorrectly with the msvc32 port later

@oandrieu - that forces me or anyone else to be developing my code using msvc or to correct later on (in CI, whatever) after I've fixed other bugs vs having GCC tell me about accidentally C89+isms at the same as my actual bugs. It's also a problem if:

  1. You're using mingw64 because it's convenient to have fast access on the command line to both a 32 and 64-bit C compiler
  2. You're using Visual Studio 2015 or later
  3. You're developing on Linux and don't have msvc but you do have mingw...

@dra27 dra27 force-pushed the c89_headers branch 3 times, most recently from 50556c3 to fb070dc Compare May 18, 2017 19:34
@dra27
Copy link
Member Author

dra27 commented May 18, 2017

msvc32 should be fixed - a little more extra care was needed to ensure that static inline works for building OCaml itself. This has the nice effect that the Caml headers no longer magically makes inline work on MSVC (because the headers use __inline__ always) - see extra code in config/m-nt.h.

@stedolan, in addition to helpfully confirming that there shouldn't be semantic worry because inline is always used in the context of static inline also made the point that because any build system compiling this way must have code somewhere to pass -std=c89 to gcc, one can easily add -D inline=__inline__ at the same time. That said, I think that the side-effect here of not ever redefining the inline keyword on MSVC is a different and more-compelling reason for the change.

@oandrieu
Copy link
Contributor

@dra27 In my experience, the most common incompatibility between old MSVC and C99 is mixing declaration and statements, wouldn't the -Wdeclaration-after-statement GCC warning option be enough ?

Another possibility would be to leave inline in the code and try to detect your special case of gcc-called-with-stdc89, something like this:

#if defined (__GNUC__) && (__STDC_VERSION__ < 199901L)
# define inline __inline__
#endif

@xavierleroy
Copy link
Contributor

The ISO C 1999 standard is old enough to vote in many countries. It makes me sad that we still cannot write the OCaml runtime system in proper C99.

This said, I'm not against the approach proposed here. But I'd rather not use __inline__ as the keyword/macro to use in runtime source code: identifiers and macro names starting with __ are "reserved" (whatever that means) in the C99 standard, and I know from experience that some C standard library headers do weird things with GCC extended keywords, such as defining __attribute__(x) to the empty string.

So, I'd rather have a macro, say Caml_inline, that expands to static inline or static __inline__ or static __inline as appropriate. (Why put static inside the macro? because extern inline or plain inline have bizarre semantics and I'd rather make sure we never run into these.)

Alternatively, @oandrieu's suggestion (#define inline __inline__ when appropriate) makes a lot of sense and is much simpler.

@xavierleroy
Copy link
Contributor

@dra27 do you wish to pursue this approach, esp. the #define inline __inline__ suggestion of @oandrieu? Or should we close?

@dra27
Copy link
Member Author

dra27 commented Sep 13, 2017

Sorry, I'd put this on the proverbial backburner! Thanks @oandrieu - I didn't know about that switch and I've now changed my original use case in opam to use that instead of --std=c89.

We should tidy up the #define inline stuff as suggested and I will try to do that in the next 48 hours (and also tweak AppVeyor and ci-build to use -Wdeclaration-after-statement

@dra27 dra27 added this to the 4.06.0 milestone Sep 13, 2017
@xavierleroy
Copy link
Contributor

Any news on this PR? If not we'll take it off the 4.06 milestone, as it is not particularly urgent.

@xavierleroy
Copy link
Contributor

Taking this PR off the 4.06 milestone.

@xavierleroy xavierleroy removed this from the 4.06.0 milestone Oct 10, 2017
@damiendoligez damiendoligez added this to the 4.07-or-later milestone Oct 11, 2017
@damiendoligez damiendoligez removed this from the consider-for-4.07 milestone Jun 5, 2018
@xavierleroy
Copy link
Contributor

No news for two years. C89 support looks less and less relevant. We should rather encourage the use of modern C standards. I'm taking the liberty to close this PR.

The inline keyword is consequently no longer forced on MSVC builds.
This GCC flag encourages development of C files which will compile
without error on older Microsoft C compilers.
@dra27 dra27 reopened this Feb 11, 2020
@dra27 dra27 changed the title Allow headers to be processed in C89 mode Aid compatibility with older Microsoft C compilers Feb 11, 2020
@dra27
Copy link
Member Author

dra27 commented Feb 11, 2020

The build failure in #9293 on msvc32 prompted me finally to finish this one off, because it would have prevented it.

PR updated:

  • @xavierleroy's suggestion to introduce Caml_inline is done. caml_stat_strdup_to_utf16 was marked inline in runtime/win32.c which is completely incorrect.
  • configure now automatically uses -Wdeclaration-after-statement if GCC is in use, which necessitates juggling in a few C files.

Combined, that means we:

  • no longer abuse the inline keyword on MSVC
  • don't waste AppVeyor time where a developer reasonably forgets to put a variable declaration only at the start of a block

I have not updated the inline keywords in stdlib/headernt.c because that file is MSVC/mingw-w64 specific and I didn't see any value in working out the various versions of __forceinline.

Copy link
Contributor

@xavierleroy xavierleroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be nice if MSVC implemented the C99 standard... But I'm afraid we have to carry that cross.

This said, even for C compilers that implement C99, it is better to use static inline instead of inline, and the Caml_inline macro encourages this good practice.

So, this PR is an improvement, and I'm in favor of merging. One suggested change below, but nothing essential.

#else
#define INLINE
#define INLINE static
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Caml_inline is available on all platforms, I would simply replace INLINE by Caml_inline in this file and delete this #ifdef nonsense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't totally sure about that, because inline was only used for GCC, but I guess that could have been dropped when we introduced the C99 requirement. I pushed a commit tidying it up.

@XVilka
Copy link
Contributor

XVilka commented Feb 12, 2020 via email

@dra27
Copy link
Member Author

dra27 commented Feb 13, 2020

Thanks, @xavierleroy - I'll merge once CI confirms the additional commit.

@XVilka - IIUC, no version of MSVC is C99-compliant. When Microsoft rewrote their C runtime library in C++ to create the Universal CRT, the C99 support was vastly improved, and consequentially some C99 things were added to the compiler, but I think their stock answer has always been that it's a C++ compiler (and I believe the adherence to ISO C++ is at least less awful...)

@dra27 dra27 merged commit d26d37b into ocaml:trunk Feb 13, 2020
@dra27 dra27 deleted the c89_headers branch February 13, 2020 15:17
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
…caml#1176)

This reverts commit 0f416573078fea425ed4bf22238232083b609f2e.

Rectifying a mistake: this change shouldn't have been pushed without more discussion and a consensus.
If we want to make this change, let's open an RFC first.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants