[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Tinycc-devel] Clarification about log message in commit 48df89e10e
From: |
Stefanos |
Subject: |
Re: [Tinycc-devel] Clarification about log message in commit 48df89e10e |
Date: |
Tue, 20 Apr 2021 01:21:50 +0300 |
> This is all a bit academic, but anyway:
>
> The difference is in "that is part of a definition" and "that is
> not part of a definition". So:
>
> int main();
>
> declares main as function but not anything about parameters (main has no
> prototype then). While:
>
> int main() { ...; return 0; }
>
> declares (and defines) main to be a function having no parameters. Even
> the first variant (i.e. missing prototype without parameter info) is no
> license to make main (or any other function) accept any number of
> parameters. This is because "any number of params" would be a stdarg
> function, which must be declared and defined with a parameter type list
> that includes an ellipsis at the end. You could call such function with
> arbitrary number and types of arguments, and the compiler wouldn't reject
> this, but at runtime it won't work. The prototype is what is checked, so
> without one no checks are done. But even without prototype the calls need
> to match the implementation of the function at run time (otherwise:
> undefined behaviour).
>
> Additionally the "or in some other implementation-defined manner" gives us
> leeway to accept more declarations than strictly required, which makes us
> okay to accept:
>
> void main(void);
>
> (i.e. without return type). That is good, because in the wild this usage
> of main() happens, so we better accept it as well.
>
> > Was this implemented intentionally or just happened?
>
> I'm not sure what "this" refers to here,
I meant the TCC tests here; my apologies for not making it clearer in the
first place.
> but we basically need to accept
> any of these forms of decls and defs of main:
>
> int main();
> int main() { ... }
> void main();
> void main() { ... }
> int main(int argc, char *argv[]);
> int main(int argc, char *argv[]) { ... }
> void main(int argc, char *argv[]);
> void main(int argc, char *argv[]) { ... }
>
> We need to accept these in such way that the user has to be able to
> write a prototype for main, and has to be able to _not_ have to write a
> prototype for it before definition. If he chooses to write a prototype it
> must be compatible with the given definition as usual.
> We need not accept other forms of main. E.g. GCC warns
> with other forms, but TCC does not. Sometimes it's convenient (when you
> know something about the C libraries implementation) to define main like
> so:
>
> int main(int argc, char *argv[], char *envp[]) { ... }
>
> or even add another one (auxv) on some libc's, so adding more checks for
> validity would have to be done carefully to not disallow valid uses in the
> wild.
>
> The reason why main() is so special-cased in the standard is historic.
>
> I'm not sure if the above answers your question(s), if not, try asking
> more ;-)
>
For the moment I think you gave me enough information to grasp.
Thank you very much.
>
> Ciao,
> Michael.