On Thu, Jun 30, 2005 at 09:33:50AM +0100, Steve Hay wrote: > Yitzchak Scott-Thoennes wrote: > > >On Mon, Jun 27, 2005 at 10:46:19AM +0100, Steve Hay wrote: > > > > > >>win32/win32.c currently generates warnings under gcc. The problem is > >>reproduced by: > >> > >>#include <process.h> > >>int main() { > >> const char *cmdname; > >> const char *const *argv; > >> return execv(cmdname, (char *const *)argv); > >>} > >> > >>which causes gcc to complain: > >> > >>test.c:5: warning: passing arg 2 of `execv' from incompatible pointer type > >> > >>In MinGW (and VC++) execv's 2nd arg is const char *const *, so simply > >>removing the cast makes it happy. However, in Borland C execv's 2nd arg > >>is just char * const * (hence the reason for the cast in the first place > >>-- must have been written by a Borland C user!), so removing the cast > >>makes bcc32 complain: > >> > >>Warning W8075 test.c 5: Suspicious pointer conversion in function main > >> > >>How can I keep both compilers (gcc and bcc32) happy? Is #ifdef hell the > >>only way, e.g. > >> > >>#ifdef __BORLANDC__ > >> return execv(cmdname, (char *const *)argv); > >>#else > >> return execv(cmdname, argv); > >>#endif > >> > >>Why does gcc complain in the first place, though? I thought that > >>passing a non const arg to a function with a const parameter was > >>generally not a problem, and indeed, VC++ didn't complain. What is > >>gcc's problem? > >> > >> > > > >There's discussion of this (that I didn't understand, but maybe you > >will) in the SUSv3 execv page, under Rationale, that implies that gcc > >is technically correct in having a problem. If you have to resort to > >ifdef hell, I'd make it check for mingw, not for __BORLANDC__, since > >mingw is what's getting the prototype wrong. > > > I didn't understand it either, and I don't understand your conclusion > that it implies gcc has a problem. Why did you think it implies that?
It says "due to a limitation of ISO C...specifying two levels of const-qualification...would disallow existing correct code" (presumably constless code). And the table shows that assigning a "const char * const []" to a "char * const []" is not valid. So I'm saying that implies gcc is correct in giving the warning. > Are you suggesting that I should write > > #ifdef __MINGW__ > return execv(cmdname, argv); > #else > return execv(cmdname, (char *const *)argv); > #endif > > ? I can't see that that is an improvement because it now applies the > cast in the VC++ case too, which doesn't need a cast since it has the > correct prototype to start with. I thought from what you said that it doesn't warn, so it wouldn't hurt to pass the args correctly. > The way I saw it is that it is Borland that gets the prototype wrong and > hence Borland that needs the cast. Borland has: int _RTLENTRY _EXPFUNC execv(const char * __path, char * const * __argv); VC+: _CRTIMP int __cdecl execv(const char *, const char * const *); MinGW: _CRTIMP int __cdecl _execv (const char*, const char* const*); SUSv3 (http://www.opengroup.org/onlinepubs/009695399/functions/execv.html): int execv(const char *path, char *const argv[]); So Borland is the only one of the three that gets it right.