cplusplus / CWG

Core Working Group
23 stars 7 forks source link

CWG2811 [basic.start.main] Clarify what it means to "use" `main` #422

Closed Eisenwave closed 5 months ago

Eisenwave commented 1 year ago

Reference (section label): [basic.start.main] p3

Short Issue Description

In [basic.start.main] paragraph 3, it is unclear what "use" of the function main means.

Long Issue description

The accepted proposal N3214 by @jensmaurer made the following change:

Replace all occurrences of the word "use" that are not intended as references to 3.2 with some other term, such as "occurrence" or "appearance" or "reference to".

However, this resolution was not correctly applied to [basic.start.main] p3:

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

This change violates the proposed resolution but might be deliberate, not accidental, because the first revision of N3154 did replace "use" with "odr-use", and this was later reverted.

It remains unclear what constitutes "use" of main and implementers seemingly disagree. Only Clang considers decltype(main) to constitute use of main (https://godbolt.org/z/6MPWfPzYK) and issues a warning:

<source>:2:24: warning: ISO C++ does not allow 'main' to be used by a program [-Wmain]
    2 |     using T = decltype(main);
      | 

It is possible that the change between revisions is accidental, not deliberate. In any case, disallowing decltype(main) is an arbitrary restriction and solves no implementation challenges. Disallowing only odr-use of main seems adequate, and matches the original C++98 restrictions exactly.

Suggested Resolution

Change [basic.start.main] p3 as follows:

 The function main shall not be
-used
+odr-used
 within the program.

See Also

Eisenwave commented 1 year ago

On a side note, this may have a normative effect on [basic.start.dynamic] p5 because whether "use" of main constitutes odr-use impacts until when dynamic initialization can be deferred exactly.

See also Stack Overflow/Why are exceptions thrown during deferred dynamic initialization not caught by main?

frederick-vs-ja commented 1 year ago

Or perhaps someone (like Clang folks?) may want to strengthen the prohibition:

~The function main shall not be used within the program.~ An expression shall not name ([basic.def.odr]) the function main in the global scope.

xmh0511 commented 1 year ago

Or perhaps someone (like Clang folks?) may want to strengthen the prohibition:

~The function main shall not be used within the program.~ An expression shall not name ([basic.def.odr]) the function main in the global scope.

I think "in the global socpe" can arise ambiguities. What does it mean?

  1. Does it mean the expression that appears in other namespaces other than global scope will be ok? 2.Or, It means the function main that inhabits the global scope

Your intent presumably is the second one.

An expression shall not name the function main whose declaration's target scope is the global scope.

int main(){}
namespace A{
   int main();
   void fun(){
      extern int main();  
      main;  // ok
   }
   void g(){
     using ::main;
     main; // error
   }
}
t3nsor commented 1 year ago

Honestly we could just say "the function ::main shall not be odr-used". No need to overcomplicate things.

Or "an id-expression that names the function ::main is ill-formed."

Eisenwave commented 1 year ago

@t3nsor the term usually used in the standard is "main function". There are 12 occurrences of it throughout various sections. Instead of "the function ::main", everywhere should just state "the ::main function".

This could be done through an editorial change where all those are updated to "::main function". This is purely editorial because the intent is entirely clear.

Eisenwave commented 1 year ago

@xmh0511 I see no value in keeping the arbitrary restriction that you can't even name ::main at all (assuming that this restriction is the current intended behavior, which isn't clear). The people over at llvm-project haven't made a case for keeping their current strict implementation either.

There could actually be value in detecting the type of main within a macro.

jensmaurer commented 11 months ago

CWG2811