Why does gcc warn about decltype(main()) but not c

2019-06-15 09:42发布

问题:

Take the following code:

int main()
{
    decltype(main()) x = 0;
    return x;
}

gcc complains:

main.cpp: In function 'int main()':
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
     decltype(main()) x = 0;
                   ^
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]

but not clang. So what about decltype(main()) raises this error? How does decltype take the address of main?

回答1:

GCC's diagnostic might not be correctly phrased in this case, because decltype doesn't need to know the address of main; it only needs to know its type. However, the warning is based on the following from the standard (§3.6.1/3):

The function main shall not be used within a program.

I suppose GCC interprets this to mean that you can't even use it in an unevaluated expression.

Clang (version 3.4 anyway) appears to not implement this rule at all, even if I turn on all the flags I can think of and even if main calls itself recursively. That's why it doesn't give you a warning.



回答2:

This topic actually came up recently in the undefined behaviour study group discussion list in the thread What does "The function main shall not be used within a program" mean?. It does not come up right away but here is where it starts in the thread with the following statement:

I don't think decltype(main()) is an odr-use, or sizeof(decltype(main)).

a very abbreviated set of responses looks like this:

True, I just don’t see what utility those would be. You might mean sizeof(decltype(&main)) in the latter case.

I think the most common non-ODR use of main would be defining it after a forward declaration, and now Steven Clamage has clarified that should be ill-formed. The broader definition of “use” as being a result of name lookup without reference to ODR looks correct now.

and:

C++98's mention of 'use' had a cross-reference to 3.2 [basic.def.odr]. C++11 no longer has the cross-reference, and was not changed to say 'odr-use', so I expect it means any use.

and so it would seem that the interpretation of section 3.6.1 Main function which says:

The function main shall not be used within a program. [...]

means any use even in unevaluated contexts and so gcc is correct here to produce an error although the message itself does not seem to make sense.

Update

It is interesting and instructive to note that the original proposal: N3154 to fix Defect report 1109 would have changed 3.6.1 to:

The function main shall not be odr-used (3.2) within a program. ...

which would have allowed the decltype example but was amended when accepted and we can see that the new proposal: N3214 changed to what we have today:

The function main shall not be used within a program

which would strongly indicate the opinion in the UB mailing list that any use of main is ill-formed is indeed correct.