what does this warning mean ?

  • Thread starter Heinrich Pumpernickel
  • Start date
E

Eric Sosman

jacob navia wrote On 09/27/07 13:42,:
The second one. The discussion is about the supposed difference
between () in a function declaration, where it means "indeterminate
number of parameters" and a function definition, where some people
here say the space between the () would be "overloaded" to mean
"void".

That interpretation is not correct IMHO.

Unless there are some other postings that haven't
reached my news server yet, yours is the first in this
thread to use the word "overloaded." No post that I
have seen has stated or implied that () and (void) are
equivalent, so I'm not sure who these "some people" are.

What I have claimed is that a function definition
like `int main()' defines a function with no parameters.
Others have claimed the same thing, and some have gone
so far as to quote the Standard's statement to that
effect. The quoted language is sufficiently direct that
there is little if any room for "interpretation."
 
J

jacob navia

Eric said:
jacob navia wrote On 09/27/07 13:42,:
Keith said:
[...]

Then, the warning I am issuing is justified!
Which one?

The second one. The discussion is about the supposed difference
between () in a function declaration, where it means "indeterminate
number of parameters" and a function definition, where some people
here say the space between the () would be "overloaded" to mean
"void".

That interpretation is not correct IMHO.

Unless there are some other postings that haven't
reached my news server yet, yours is the first in this
thread to use the word "overloaded." No post that I
have seen has stated or implied that () and (void) are
equivalent, so I'm not sure who these "some people" are.

What I have claimed is that a function definition
like `int main()' defines a function with no parameters.

My warning was

"missing prototype for main()\n"
Others have claimed the same thing, and some have gone
so far as to quote the Standard's statement to that
effect. The quoted language is sufficiently direct that
there is little if any room for "interpretation."

No, the language is ambiguous and needed DR 317 to
clarify things. I am correct. There is NO prototype
for a function with () in the parameter list.
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

No, the language is ambiguous and needed DR 317 to clarify things.

No, the standard is unambiguous on () in function definitions, which is
why no changes were made as a result of the DR.
 
J

jacob navia

Harald said:
No, the standard is unambiguous on () in function definitions, which is
why no changes were made as a result of the DR.

Well, if that DR was needed it means that to be certain of the
unambiguous wording it was better to ask the question isn't it?

We have discussed here that at length with some citing this
and another citing that, and we could not get to a solution. OK,
after you say the answer of the committee, yes I believe it,
the wording is unambiguous ... :)
 
E

Eric Sosman

jacob navia wrote On 09/27/07 15:10,:
Eric said:
jacob navia wrote On 09/27/07 13:42,:
Keith Thompson wrote:


[...]


Then, the warning I am issuing is justified!

Which one?


The second one. The discussion is about the supposed difference
between () in a function declaration, where it means "indeterminate
number of parameters" and a function definition, where some people
here say the space between the () would be "overloaded" to mean
"void".

That interpretation is not correct IMHO.

Unless there are some other postings that haven't
reached my news server yet, yours is the first in this
thread to use the word "overloaded." No post that I
have seen has stated or implied that () and (void) are
equivalent, so I'm not sure who these "some people" are.

What I have claimed is that a function definition
like `int main()' defines a function with no parameters.


My warning was

"missing prototype for main()\n"

That was one of them. Another was
'int main()' is a non-ANSI definition

.... and the claim it makes is non-factual.
No, the language is ambiguous and needed DR 317 to
clarify things.

There is no ambiguity. The committee reviewed the
report of the defect, responded that there was none (and
explained their reasoning), and closed the DR.

The fact that a defect report is filed does not prove
that a defect actually exists. Observe how strenuously
you yourself are denying any defect in lcc-win32 despite
the defect report that originated this very thread!
I am correct. There is NO prototype
for a function with () in the parameter list.

Nobody says there is. Furthermore, most posters agree
that *that* warning (issued twice, really) is reasonable.
It's the one about "non-ANSI" that's wrong. There is nothing
"non-ANSI" about `int main(){...}'. The ANSI Standard and
all its successors to date have all defined this construct,
have all agreed on its meaning, and have all agreed that it
is a valid definition of the `main' function for a hosted
environment.

The compiler may, of course, issue all the warnings
it wants. This particular warning is not "incorrect" in
the sense of contravening the language standard, but is
"incorrect" in the sense that it diminishes QoI. I urge
you to fix it in a future release (but I don't think it's
worth issuing a Mattel-style recall over it).
 
K

Kenneth Brody

Ben said:
int foo()
{
return 1;
}

int main(void)
{
foo();
foo(10);
}
[...]
No. int foo() { code } is not a prototype for foo, so foo(10) is not a
constraint violation -- no diagnostic required. Gcc on max verbosity
tells me that the definition of foo does not constitute a prototype for
it which is certainly useful.

I wouldn't consider it a prototype, either. However, somewhere
elsethread, I got the impression that people were arguing that
"int main() {...}" constituted a prototype equivalent to
"int main(void)". Specifically, they were complaining that lcc
was issuing a warning.

[...]

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Keith Thompson

I don't have the energy to figure it out, but I'll take your word for
it... especially since, re-reading 6.5.4.3 in context, it does seem
that "empty list" refers to an empty identifier list.

So that's really ugly :(

int main() { ... } and int main(void) { ... } do indeed have very
subtly different semantics, which is dumb: after seeing either of them
the compiler knows exactly the signature of main, but only in one case
is it allowed to use this knowledge if it encounters main later in the
same translation unit. Yuck!

Yes, but it's a necessary ugliness. See my explanation in comp.std.c.
 
K

Keith Thompson

jacob navia said:
Eric said:
jacob navia wrote On 09/27/07 13:42,:
Keith Thompson wrote:
[...]

Then, the warning I am issuing is justified!
Which one?

The second one. The discussion is about the supposed difference
between () in a function declaration, where it means "indeterminate
number of parameters" and a function definition, where some people
here say the space between the () would be "overloaded" to mean
"void".

That interpretation is not correct IMHO.
Unless there are some other postings that haven't
reached my news server yet, yours is the first in this
thread to use the word "overloaded." No post that I
have seen has stated or implied that () and (void) are
equivalent, so I'm not sure who these "some people" are.
What I have claimed is that a function definition
like `int main()' defines a function with no parameters.

My warning was

"missing prototype for main()\n"
Others have claimed the same thing, and some have gone
so far as to quote the Standard's statement to that
effect. The quoted language is sufficiently direct that
there is little if any room for "interpretation."

No, the language is ambiguous and needed DR 317 to
clarify things. I am correct. There is NO prototype
for a function with () in the parameter list.

Yes, given

int main() { /* ... */ }

there is no prototype. Your warning about a "missing prototype" is
ok; the word "missing" could imply that a prototype is required, which
is not the case, but since the warning is only issued at a high
diagnostic level where the user in effect asked for prototypes to be
required, I won't quibble about it. (Well, not much.)

I think one person in this discussion said or implied that there is a
prototype in that case. That person was mistaken, and you were right.
(You might want to consider not making quite such a big deal about
that fact; you probably don't want to imply that your being right
about something is an unusual occasion.)

But that is not the only thing we're discussing. Another of the three
(!) warnings you issue for that line says that the declaration is
"non-ANSI". That is clearly and unambiguously incorrect. Functions
without prototypes are obsolescent, but they are not obsolete; they
are just as much a part of the ANSI/ISO standard (C89, C90, C95, or
C99) as prototypes. Warning about an unprototyped function is fine,
but *please* make sure that the warning message itself is factually
correct.

An argument can be made that 'int main() { /* ... */ }' is invalid in
C90 and C99 (specifically that it invokes undefined behavior unless
the implementation documents it as an allowed form), but on further
examination I'm 99% convinced that the intent is for it to be valid
(i.e., that a conforming compiler may not reject it). I've discussed
this at greater length in comp.std.c.
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

Well, if that DR was needed it means that to be certain of the
unambiguous wording it was better to ask the question isn't it?

Yes, it means the standard is not as clear as it could (and possibly
should) be, but not more than that.
 
K

Keith Thompson

Kenneth Brody said:
I wouldn't consider it a prototype, either. However, somewhere
elsethread, I got the impression that people were arguing that
"int main() {...}" constituted a prototype equivalent to
"int main(void)". Specifically, they were complaining that lcc
was issuing a warning.

They were wrong.

The two are equivalent *as definitions*, in that they both define main
as a function with no parameters. But they differ *as declarations*,
in that the old-style non-prototype '()' form doesn't cause incorrect
calls to be constraint violations.
 
O

Old Wolf

int main() is ugly and obsolescent.

It is not ugly to me. The function takes no arguments so
there is nothing inside the parentheses. That's how it is
in almost every other programming language that has
functions.

Requiring text to indicate lack of parameters is ugly.
 
K

Keith Thompson

Old Wolf said:
It is not ugly to me. The function takes no arguments so
there is nothing inside the parentheses. That's how it is
in almost every other programming language that has
functions.

Requiring text to indicate lack of parameters is ugly.

And necessary given the need for backward compatibility with pre-ANSI
C.
 
U

U

[crossposted to comp.compilers.lcc]

what does this warning mean ?


#include <stdio.h>

int main()
{
long l = 100;

printf("l is %li\n", l * 10L);

return 0;
}


when i compile this program with lcc-win32 it prints

lcc -A -ansic -O long.c -o long.obj
Warning c:\tmp\long.c: 4 old-style function definition for 'main'
Warning c:\tmp\long.c: 4 missing prototype for 'main'
Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
Expected long int got int
0 errors, 4 warnings

[snip]

<OT group="c.l.c">

One thing I observed a long time ago is that lcc-win32 sometimes
produces warnings for operations on signed types but not for the
same operations on unsigned types.

*long -> *int ==> diagnostic
*unsigned long -> *unsigned int ==> no diagnostic

The same seems to be true for printf() arguments as well,

long l; unsigned long ul;
printf("%li\n", l * 10); ==> diagnostic
printf("%lu\n", lu * 10); ==> no diagnostic


/*** begin lcctest.c ***/

#include <stdio.h>

volatile void *foo;

int main(void)
{
long l = 100;
unsigned long ul = 100;

int *pi = &l; /* line 12: produces diagnostic */
unsigned int *pui = &ul; /* line 13: no diagnostic */

/* prevent prev. two statements from being optimized away */
foo = pi; foo = pui;

printf(" l * 10: %li\n", l * 10);
printf(" ul * 10: %lu\n", ul * 10);

return 0;
}

/*** end lcctest.c ***/

$ wine lcc -ansic -A -O lcctest.c
Warning z:\src\clc\lcctest.c: 12 assignment of pointer to long int to
pointer to int
Warning z:\src\clc\lcctest.c: 18 printf argument mismatch for format i.
Expected long int got int
0 errors, 2 warnings

</OT>
 
S

somenath

Yes: the latter provides a prototype declaration of the function
(in this case, of main()), as if one had written:

int main(void);
int main(void) { ... }

The former fails to provide a prototype declaration, only a
type-declaration, as if one had written:

int main();
int main() { ... }


Change the word "allowed" to "required", and you have it precisely.

A compiler is always allowed to produce extra diagnostics. It
is only *required* to produce a diagnostic for this particular
error for a prototype mismatch. Hence, the code fragment:

/* x.c */
int f();
int g(void);

int h(void) {
return f(0) + g(0);
}

I am little confuse about the example
requires a diagnostic, because g(0) supplies an argument where the
compiler is required to remember that g() takes no arguments.
While I compile with gcc as
I get the bellow mentioned warnings
gcc -Wall x.c
x.c: In function `h':
x.c:12: too many arguments to function `g'

This I can undersatnd as it is explained in the above sentences .

If
the compiler can somehow tell that f() also takes no arguments --
e.g., by looking at a separate file like "f.c" or "f.o", or looking
elsewhere in this same file (x.c) and finding the actual code for
f(), or reading the design documentation for the project, or perhaps
even by reading the programmer's mind -- it is *allowed* to warn
about f().

(Writing a compiler that reads the project documentation and/or
the programmer's mind is perhaps a little ambitious. :) Having
the compiler -- which includes the thing usually called "the linker",
in this case -- examine every file that is combined to make the
final executable is, however, quite feasible. The diagnostic for
the mismatch between an f() that takes no arguments and the call
f(0) may wind up looking something like "unable to find symbol
$function$int$f$int$", perhaps, although a "nice" linker might also
then back-translate that to "unable to find int f(int); I did find
an int f(void) but that does not match; perhaps the call at line
45 in h.c is incorrect".)

But If I change the code as mentioned bellow

#include<stdio.h>

int f();
int g(void);

int main(void)
{
return 0;
}

int h(void) {
return f() + g();
}

I get the linker error as

gcc -Wall x.c
/tmp/cc6rowkR.o(.text+0x1f): In function `h':
: undefined reference to `f'
/tmp/cc6rowkR.o(.text+0x26): In function `h':
: undefined reference to `g'
collect2: ld returned 1 exit status

could you please let me know why it is throwing such errors ?
 
S

Stephen Sprunk

somenath said:
But If I change the code as mentioned bellow

#include<stdio.h>

int f();
int g(void);

int main(void)
{
return 0;
}

int h(void) {
return f() + g();
}

I get the linker error as

gcc -Wall x.c
/tmp/cc6rowkR.o(.text+0x1f): In function `h':
: undefined reference to `f'
/tmp/cc6rowkR.o(.text+0x26): In function `h':
: undefined reference to `g'
collect2: ld returned 1 exit status

could you please let me know why it is throwing such errors ?

You declared the functions, but you did not define them, i.e. there is no
body to your functions available. If you had enabled optimization, gcc
might have removed f(), g(), and h() entirely since they're never called
from main().

<OT>
"undefined reference to 'foo'" is almost always ld telling you that you
forgot to define the named function or link in a required library that
contains said function. If you only want to check for compilation errors
without trying to link, add "-c" to the gcc command line.
</OT>

S
 
R

Richard Bos

Chris Hills said:
The sooner we get the Euro and fully integrated with Europe the better.

One one condition: that you get out of the United States of America.

Richard
 
P

Philip Potter

Old said:
It is not ugly to me. The function takes no arguments so
there is nothing inside the parentheses. That's how it is
in almost every other programming language that has
functions.

Yes, and in C++ 'int main()' is definitely nicer than int main(void). But given
the C standard as we have it, writing int main() is ugly because of the mismatch
between the meaning of empty parameter lists in (non-definining) declarations
and definitions.
Requiring text to indicate lack of parameters is ugly.

I agree.
 
J

John J. Smith

U wrote:
[followup set to c.l.c]
[crossposted to comp.compilers.lcc]

what does this warning mean ?


#include <stdio.h>

int main()
{
long l = 100;

printf("l is %li\n", l * 10L);

return 0;
}


when i compile this program with lcc-win32 it prints

lcc -A -ansic -O long.c -o long.obj
Warning c:\tmp\long.c: 4 old-style function definition for 'main'
Warning c:\tmp\long.c: 4 missing prototype for 'main'
Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
Expected long int got int
0 errors, 4 warnings

[snip]

<OT group="c.l.c">

One thing I observed a long time ago is that lcc-win32 sometimes
produces warnings for operations on signed types but not for the
same operations on unsigned types.

*long -> *int ==> diagnostic
*unsigned long -> *unsigned int ==> no diagnostic

The same seems to be true for printf() arguments as well,

long l; unsigned long ul;
printf("%li\n", l * 10); ==> diagnostic
printf("%lu\n", lu * 10); ==> no diagnostic


/*** begin lcctest.c ***/

#include <stdio.h>

volatile void *foo;

int main(void)
{
long l = 100;
unsigned long ul = 100;

int *pi = &l; /* line 12: produces diagnostic */
unsigned int *pui = &ul; /* line 13: no diagnostic */

/* prevent prev. two statements from being optimized away */
foo = pi; foo = pui;

printf(" l * 10: %li\n", l * 10);
printf(" ul * 10: %lu\n", ul * 10);

return 0;
}

/*** end lcctest.c ***/

$ wine lcc -ansic -A -O lcctest.c
Warning z:\src\clc\lcctest.c: 12 assignment of pointer to long int to
pointer to int
Warning z:\src\clc\lcctest.c: 18 printf argument mismatch for format i.
Expected long int got int
0 errors, 2 warnings

</OT>

Um... wouldn't line 13 be a constraint violation and every
conforming compiler is *required* to issue a diagnostic even
when not at the highest warning level? (even warning about
line 12 is not issued without "-A".)

I have extended your test with some suspicious pointer
assignments involving 'char' and no diagnostic is issued for
those either, even at the highest warning level.

Gcc warns about lines 12, 13, 14, and 15.

Which of those are really required by the standard?


Modified test and compiler output follows.

/*** begin lcctest.c (modified by jss) ***/

#include <stdio.h>

volatile void *foo;

int main(void)
{
long l = 100;
unsigned long ul = 100;
char c = 1;

int *pi = &l; /* line 12 */
unsigned int *pui = &ul; /* line 13 */
signed char *psc = &c; /* line 14 */
unsigned char *puc = &c; /* line 15 */

/* prevent prev. two statements from being optimized away */
foo = pi; foo = pui; foo = psc; foo = puc;

printf(" l * 10: %li\n", l * 10);
printf(" ul * 10: %lu\n", ul * 10);

return 0;
}

/*** end lcctest.c ***/

lcc output:

$ wine lcc -ansic -A -O lcctest.c
Warning z:\home\jss\src\clc\lcctest.c: 14 assignment of pointer to long int
to pointer to int
Warning z:\home\jss\src\clc\lcctest.c: 22 printf argument mismatch for
format i. Expected long int got int
0 errors, 2 warnings

gcc output:

$ gcc-4.2 -Wall -W -ansi -pedantic -O2 -c lcctest.c
lcctest.c: In function 'main':
lcctest.c:13: warning: initialization from incompatible pointer type
lcctest.c:14: warning: initialization from incompatible pointer type
lcctest.c:15: warning: pointer targets in initialization differ in
signedness
lcctest.c:16: warning: pointer targets in initialization differ in
signedness
 
J

jacob navia

John said:
gcc output:

$ gcc-4.2 -Wall -W -ansi -pedantic -O2 -c lcctest.c
lcctest.c: In function 'main':
lcctest.c:13: warning: initialization from incompatible pointer type
lcctest.c:14: warning: initialization from incompatible pointer type
lcctest.c:15: warning: pointer targets in initialization differ in
signedness
lcctest.c:16: warning: pointer targets in initialization differ in
signedness

MSVC++ says:
------------------------------------------------
twarn1.c(11) : warning C4057: 'initializing' : 'int *' differs in
indirection to slightly
different base types from 'long *'
twarn1.c(12) : warning C4057: 'initializing' : 'unsigned int *' differs
in indirection to
slightly different base types from 'unsigned long *'
twarn1.c(14) : warning C4057: 'initializing' : 'unsigned char *' differs
in indirection to
slightly different base types from 'char *'
-----------------------------------------------
only at the highest warning level (-W4)

At the default level absolutely NO warnings are issued.

I am ready to change the compiler if any contradiction
to the standard is detected. I do not see here why a
warning is mandatory however.

jacob
 
C

Chris Hills

Richard Bos said:
One one condition: that you get out of the United States of America.

Absolutely!.... I couldn't agree more . Though the US can keep Blair
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,113
Latest member
Vinay KumarNevatia
Top