3 ms·
Regardless of how you think a modern compiler in C99 mode should behave, the fact is that "gcc -std=c90" generates code that returns an arbitrary value from mai
by _kst_ 5y ago
Regardless of how you think a modern compiler in C99 mode should behave, the fact is that "gcc -std=c90" generates code that returns an arbitrary value from main if no return or exit is executed.
clang doesn't do this as far as I can tell -- though it's difficult to be sure, since returning a status of 0 is valid C90 behavior.
- ikerdanzel 5y agoFault is at gcc. The option c90 should be deprecated totally removed. It is running Windows 11 and expecting program written for Windows 3.1 still runs. Those who still runs old copy of gcc, they know what they are getting. They assume the risk.
- kazinator 5y agoI would say that is a bug. More than 22 years ago, ISO C introduced this requirement for a reason. The reason was almost certainly the desire to fix that issue for as many C programs as possible, and that there was no intent that there be an exceptions for C programs that happen to request C90 compatibility in their accompanying Makefile. An indeterminate termination status causes real problems like, oh, if those programs are run out of POSIX script in "set -e" mode, the script will randomly terminate at that point. It has consequences. This requirement plugged a hole; when those programs are recompiled with compiler which adopts the requirement, that issue is fixed. From the developer's perspective, using GCC in C90 mode does mean they should be prepared to conform to C90 and not do things like that falling off the end of main if there is any risk that the termination status matters. In my original comment above, I made remarks to that effect. But that developer isn't the only stake holder. A developer working in C90 can still accidentally forget the return, and some downstream user who doesn't even program in C is affected by that. We also have to think from the point of view of a that downstream user building and operating a program received from such a developer. The user wants a program that has a successful termination status when it terminates normally an de facto successfully; the user doesn't care whether that comes from the compiler, or whether the program takes care of it. It's pretty shoddy from that not to come from the compiler, almost a quarter century after it was declared that, in the C language, "int main(void) {}" is now a successfully terminating program! When you request dialect compatibility from an implementation, you don't want old bugs to come back, unless they are specifically required. Your downstream user doesn't want that, certainly. If you really want old bugs, you go get the actual old compiler; -std=c90 passed to GCC 11 does not mean "emulate every detail of GCC 1.x".
- gpderetta 5y agoBut there aren't a lot of good reasons to compile with C90 or older these days (for portability you can just restrict yourself to the portable subset). I suspect the flag is there to support old unmaintained programs and it makes sense not to change their behaviour (because nobody is going to fix bugs in them), as long as it is not a big burden on the compiler. In fact, think of old K&R C instead of C90. I wouldn't be surprised if there are old unix tools that relied on propagating the result of the last operation executed into main. In fact sometimes gcc has added explicit flags to enable this kind of "traditional" behaviour. Clang was written well after C99, so it didn't make sense to implement the old traditional behaviour there in the first place.
- kazinator 5y ago> aren't a lot of good reasons to compile with C90 Sure there are, like: - Project doesn't want mixed declarations and statements creeping into the code base - Project doesn't want want variable-length arrays creeping into the code base. - Project doesn't want new footguns in preprocessing. - Project hates mixtures of // and /.../ comments. I think the Linux kernel is still using C90 (with GNU extensions). > tools that relied on propagating the result of the last operation executed into main. In all the situations in which the compiler has enough information to indicate the insert of a "return 0", it could emit a diagnostic (if it is in C90 mode). foo.c:17: warning: main returns without a value [-std=c90, -Wmain-return] The user is alerted to this and can look at the code and decide whether it's just missing a "return last_operation();" or whether it should be "(void) last_operation(); return 0;". -std=c90 is not a good option for requesting "I want the random contents of the return register left behind by the last function called in main to be the return value of main, if possible".