[cfe-dev] Calling main() is ub based optimizations

David Chisnall via cfe-dev cfe-dev at lists.llvm.org
Mon Nov 14 08:38:14 PST 2016


On 14 Nov 2016, at 16:29, Mehdi Amini <mehdi.amini at apple.com> wrote:
> 
> 
>> On Nov 14, 2016, at 3:11 AM, David Chisnall via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>> 
>> On 14 Nov 2016, at 10:58, Ben Taylor <brtaylor92 at gmail.com> wrote:
>>> 
>>> The relevant piece of standardese seems to be 3.6.1.3 in the C++17 working draft (n4606) standard, which reads in part:
>>> 
>>> "The function main shall not be used within a program. The linkage (3.5) of main is implementation-defined. A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill-formed. The main function shall not be declared with a linkage-specification (7.5). A program that declares a variable main at global scope or that declares the name main with C language linkage (in any namespace) is ill-formed."
>>> 
>>> So the cases you suggest, by my reading, should not be UB but rather a compile error.
>> 
>> It sounds as if calling main from C++ should be a compile error.  It’s not clear what’s expected to happen if a C compilation unit calls a C++ main.
> 
> Isn’t the very beginning "The function main shall not be used within a program” enough?

No, because this rule does not exist in the C standard and, from the perspective of a C compilation unit the main function is just another C function.  The fact that a function in another compilation unit is implemented in a different language makes calling it UB.  Consider two compilation units written in the common subset of C and C++:

Compilation unit A contains main(), which calls foo().

Compilation unit B calls main() the first time that it’s called, and returns otherwise.

If these are both compiled as C, this is valid code.
If these are both compiled as C++, then compilation unit B should be a compile-time error.
If A is compiled as C and B is compiled as C++, then B should be a compile-time error.
If A is compiled as C++ and B is compiled as C then we have a problem: is is well-defined behaviour in C for B to contain a call to main(), but it is UB in C++ for the main defined in A to be called.

This means that we don’t know if B is relying on UB unless we know whether A is compiled as C or C++ code.  This is a horrible situation: flipping a compiler switch in A changes whether B is UB or not.

David




More information about the cfe-dev mailing list