473,498 Members | 2,023 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

identifier scope in old-style declarations

Hello,

with gcc-4.2.3, this does not compile:

typedef int foo;
int f(foo)
int foo;
{
return foo;
}

The error message is rather explicit ("old-style parameter declarations
in prototyped function definition"), which means that the compiler, when
encountering the "foo" on the second line, considered it to be a type
name, and not an argument name which would override the global type
definition within the function scope.

I understand, from a practical point of view, that doing otherwise would
mess the compiler (it would contradict the almost-LALR(1) property of
the C grammer). However, I cannot find in the C standard where such an
override is forbidden. Right now, it seems to me that the construction
is ambiguous.

Could someone shed some light on this ?
--Thomas Pornin
Aug 6 '08 #1
21 3954
Thomas Pornin wrote:
Hello,

with gcc-4.2.3, this does not compile:

typedef int foo;
int f(foo)
int foo;
{
return foo;
}

The error message is rather explicit ("old-style parameter
declarations in prototyped function definition"), which means that the
compiler, when encountering the "foo" on the second line, considered
it to be a type name, and not an argument name which would override
the global type definition within the function scope.
Hmm, I don't know all the details of pre-ANSI C, but I fail to see how
you can use a type alias in place of an lvalue. Foo is an alias for
int, a type. You need an object or expression of foo within the
parameter list to f() and in the subsequent type declaration and in the
return statement.

<snip>

typedef int foo;
foo fx(f)
foo f;
{
return f;
}

main() { fx(); return 0; }

Aug 6 '08 #2
Thomas Pornin wrote:
Hello,

with gcc-4.2.3, this does not compile:

typedef int foo;
int f(foo)
int foo;
{
return foo;
}

The error message is rather explicit ("old-style parameter declarations
in prototyped function definition"), which means that the compiler, when
encountering the "foo" on the second line, considered it to be a type
name, and not an argument name which would override the global type
definition within the function scope.

I understand, from a practical point of view, that doing otherwise would
mess the compiler (it would contradict the almost-LALR(1) property of
the C grammer). However, I cannot find in the C standard where such an
override is forbidden. Right now, it seems to me that the construction
is ambiguous.

Could someone shed some light on this ?
Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
identifier declared as a typedef name shall not be redeclared as a
parameter. [...]"

--
Er*********@sun.com

Aug 6 '08 #3
According to Eric Sosman <Er*********@sun.com>:
Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
identifier declared as a typedef name shall not be redeclared as a
parameter. [...]"
Well spotted ! Thanks.
--Thomas Pornin
Aug 6 '08 #4
Eric Sosman wrote:
Thomas Pornin wrote:
>Hello,

with gcc-4.2.3, this does not compile:

typedef int foo;
int f(foo)
int foo;
{
return foo;
}

The error message is rather explicit ("old-style parameter declarations
in prototyped function definition"), which means that the compiler, when
encountering the "foo" on the second line, considered it to be a type
name, and not an argument name which would override the global type
definition within the function scope.

I understand, from a practical point of view, that doing otherwise would
mess the compiler (it would contradict the almost-LALR(1) property of
the C grammer). However, I cannot find in the C standard where such an
override is forbidden. Right now, it seems to me that the construction
is ambiguous.

Could someone shed some light on this ?

Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
identifier declared as a typedef name shall not be redeclared as a
parameter. [...]"
But that's only the case if the declarator includes an _identifier list_, but
in the example above contains a _parameter type list_; so 6.9.1p5 applies:
"[...] No declaration list shall follow." which matches the error message
above.

- Huibert.
Aug 6 '08 #5
According to santosh <sa*********@gmail.com>:
Hmm, I don't know all the details of pre-ANSI C, but I fail to see how
you can use a type alias in place of an lvalue.
You can override names in inner scopes. This works for variables,
but also for type names. For instance, this compiles and works:

typedef int foo;
int f(int foo)
{
return foo;
}

Here, the identifier "foo" is redefined in an inner scope (the
function); within the function, when "foo" is encountered, it designates
the function argument. Outside of the function, the global typedef
prevails.

My question was: if it works with a new-style function definition (with
a prototype, as shown above), why does it not work with an old-style
function definition (with a list of variable names, and extra
declarations, as shown in my previous post) ? Eric Sosman found the
paragraph I had missed in the C standard, i.e. 6.9.1/6, which
explicitely rules out the override of a typedefed name with an old-style
parameter.
--Thomas Pornin
Aug 6 '08 #6
According to Huibert Bol <hu*********@quicknet.nl>:
But that's only the case if the declarator includes an _identifier
list_, but in the example above contains a _parameter type list_
Ah, that's the whole point. If the list is parsed as a parameter type
list, then the presence of the declarations is a violation, and so is
the lack of parameter name (unnamed parameters are allowed only in
prototypes without a function definition). The question was: what
prevents the compiler from parsing the list as an identifier list ? And
the answer is: this would imply that an identifier in this list
overrides a typedefed name at file scope, an occurrence which 6.9.1/6
specifically forbids (overrides of typedefed names with argument names
is allowed only with a new-style prototype, not with an old-style
identifier list).
--Thomas Pornin
Aug 6 '08 #7
Huibert Bol wrote:
Eric Sosman wrote:
>Thomas Pornin wrote:
>>Hello,

with gcc-4.2.3, this does not compile:

typedef int foo;
int f(foo)
int foo;
{
return foo;
}

The error message is rather explicit ("old-style parameter declarations
in prototyped function definition"), [...]
Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
identifier declared as a typedef name shall not be redeclared as a
parameter. [...]"

But that's only the case if the declarator includes an _identifier list_, but
in the example above contains a _parameter type list_; so 6.9.1p5 applies:
"[...] No declaration list shall follow." which matches the error message
above.
If the `(foo)' in the O.P.'s first line is taken as a parameter
list, it violates 6.9.1p5. If it is taken as an identifier list,
it violates 6.9.1p6. It is invalid either way, and diagnosing one
violation is as good as diagnosing the other.

There's often some ambiguity in pinpointing "the" error in an
erroneous source. Fundamentally, all that's really known is that
the source is incorrect; diagnosing the nature of its incorrectness
involves imagining a plausible correct source and describing the
"edit distance" between them. Since there are many, many possible
correct sources, there are many possible diagnoses.

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)

--
Er*********@sun.com

Aug 6 '08 #8
Eric Sosman wrote:
For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
It prints an additional newline ;-)

- Huibert.
Aug 6 '08 #9

"Huibert Bol" <hu*********@quicknet.nlwrote in message
news:g7**********@registered.motzarella.org...
Eric Sosman wrote:
> For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)

It prints an additional newline ;-)
Doubtful it will print anything...
it's missing the function called at program startup.
Aug 6 '08 #10
Mark B. wrote:
"Huibert Bol" <hu*********@quicknet.nlwrote in message
news:g7**********@registered.motzarella.org...
>Eric Sosman wrote:
>> For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)

It prints an additional newline ;-)

Doubtful it will print anything...
it's missing the function called at program startup.
Dûh, Eric never said it was a complete program!

- Huibert.
Aug 6 '08 #11
Eric Sosman wrote:

<snip>
There's often some ambiguity in pinpointing "the" error in an
erroneous source. Fundamentally, all that's really known is that
the source is incorrect; diagnosing the nature of its incorrectness
involves imagining a plausible correct source and describing the
"edit distance" between them. Since there are many, many possible
correct sources, there are many possible diagnoses.

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
Well I suppose there would be no error until the last phase of
translation, which will fail because main is not defined, (and you have
not told us if the program is freestanding, in which case it would be
correct, provided the contents of stdio.h and the definition for puts
are supplied by the user.)

Aug 6 '08 #12

"Huibert Bol" <hu*********@quicknet.nlwrote in message
news:g7**********@registered.motzarella.org...
Mark B. wrote:
>"Huibert Bol" <hu*********@quicknet.nlwrote in message
news:g7**********@registered.motzarella.org...
>>Eric Sosman wrote:

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)

It prints an additional newline ;-)

Doubtful it will print anything...
it's missing the function called at program startup.

Dûh, Eric never said it was a complete program!
Yet his claim that there is an error in the code suggests
that it should be... unless we have requirements on return
values from functions named 'man();' that I don't know
about...

Aug 6 '08 #13
santosh wrote:
Eric Sosman wrote:

<snip>
> There's often some ambiguity in pinpointing "the" error in an
erroneous source. Fundamentally, all that's really known is that
the source is incorrect; diagnosing the nature of its incorrectness
involves imagining a plausible correct source and describing the
"edit distance" between them. Since there are many, many possible
correct sources, there are many possible diagnoses.

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)

Well I suppose there would be no error until the last phase of
translation, which will fail because main is not defined, (and you
have not told us if the program is freestanding, in which case it
would be correct, provided the contents of stdio.h and the definition
for puts are supplied by the user.)
Just to followup, many knowledgeable members of this group have
previously said that an implementation is not required to reject the
translation of any program that does not contain a selected #error
directive. In light of that I would amend my answer above and say that
no error need be emitted by a compiler for the translation unit given
above by Eric. A conforming implementation could insert it's own main
and invoke man from it.

Aug 6 '08 #14
Eric Sosman wrote:
[...]
There's often some ambiguity in pinpointing "the" error in an
erroneous source. Fundamentally, all that's really known is that
the source is incorrect; diagnosing the nature of its incorrectness
involves imagining a plausible correct source and describing the
"edit distance" between them. Since there are many, many possible
correct sources, there are many possible diagnoses.

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
Huibert Bol, Mark B [Diputsur], and santosh have between them
described two errors in this code. To their credit, they did not
get sidetracked by the blatant red herring, either! But they all
overlooked the *real* error, which is that the code prints "Hello,
world!\n\n" instead of "Hello, world!\a\n" ;-)

Anyway, that's my illustration of the ambiguity of diagnostics.
One of the first lessons programmers learn is that error messages,
no matter how detailed and specific, may mean only "Something is
wrong somewhere." This is a consequence of the fact that the mapping
from incorrect sources to correct sources is many-to-many.

--
Er*********@sun.com
Aug 6 '08 #15
santosh <sa*********@gmail.comwrites:
[...]
>Eric Sosman wrote:
[...]
>> For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
[...]
Just to followup, many knowledgeable members of this group have
previously said that an implementation is not required to reject the
translation of any program that does not contain a selected #error
directive.
Right.
In light of that I would amend my answer above and say that
no error need be emitted by a compiler for the translation unit given
above by Eric.
Compilers don't emit errors; they emit diagnostic messages.

But I think you're conflating two different things: the cases in which
a compiler must reject a translation unit (only if it contains a
selected "#error"), and the cases in which it must issue a diagnostic
message (if there's a violation of a constraint or syntax rule).

The quoted code contains none of those things, and in fact it's
perfectly correct -- as far as the compiler can tell. If this were
real code, it would be *likely* that "man" rather than "main" was a
typo, but it happens to be a typo that changes a correct translation
unit to a different correct translation unit. A sufficiently clever
compiler could warn about it (or about anything), but there's no
requirement for it to do so.
A conforming implementation could insert it's own main
and invoke man from it.
An implementation is specifically forbidden to declare a prototype for
main (C99 5.1.2.2.1p1); that includes a prototype that's part of a
definition. Conceivably an implementation could provide a
non-prototyped definition, but that would be silly.

On the other hand, some tool in the environment (that's not considered
part of the C implementation) could always provide a definition for
main. Typically that tool is a text editor that you use to write your
own definition of main, but it could be something else.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 6 '08 #16
Eric Sosman wrote:
>
.... snip ...
>
For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
What error? The result is linkable, but can't be a program. It
always returns 0, barring a write error. Lacking a header file,
linking will require an extrn statement or equivalent in the
caller.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Aug 6 '08 #17
Eric Sosman wrote:
Eric Sosman wrote:
>[...]
There's often some ambiguity in pinpointing "the" error in an
erroneous source. Fundamentally, all that's really known is that
the source is incorrect; diagnosing the nature of its incorrectness
involves imagining a plausible correct source and describing the
"edit distance" between them. Since there are many, many possible
correct sources, there are many possible diagnoses.

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)

Huibert Bol, Mark B [Diputsur], and santosh have between them
described two errors in this code. To their credit, they did not
get sidetracked by the blatant red herring, either! But they all
overlooked the *real* error, which is that the code prints "Hello,
world!\n\n" instead of "Hello, world!\a\n" ;-)
Why is that an error? There was no description of a requirement
for a single \n.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Aug 6 '08 #18
CBFalconer wrote:
Eric Sosman wrote:
>Eric Sosman wrote:
>>[...]
There's often some ambiguity in pinpointing "the" error in an
erroneous source. Fundamentally, all that's really known is that
the source is incorrect; diagnosing the nature of its incorrectness
involves imagining a plausible correct source and describing the
"edit distance" between them. Since there are many, many possible
correct sources, there are many possible diagnoses.

For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
Huibert Bol, Mark B [Diputsur], and santosh have between them
described two errors in this code. To their credit, they did not
get sidetracked by the blatant red herring, either! But they all
overlooked the *real* error, which is that the code prints "Hello,
world!\n\n" instead of "Hello, world!\a\n" ;-)

Why is that an error? There was no description of a requirement
for a single \n.
In fact, there were no stated requirements whatsoever! This was
my nod toward yet another sort of "error:" the program that compiles
correctly and runs to completion without crashing or doing anything
untoward, but nonetheless fails to fulfill the purposes of its author.
Compilers and tools have a *very* hard time diagnosing such errors,
although warnings like "suggest parentheses around assignment used
as truth value" for `if (a = b)' are attempts to do so.

Y'know those posts that come up all too frequently, showing a
chunk of code and asking why it doesn't "work" without explaining
what the program is intended to do? The people who post such things
have, I think, failed to understand the difference between errors
of the kind that result in invalid programs and those producing
valid programs that misbehave.

--
Er*********@sun.com
Aug 6 '08 #19
On Wed, 06 Aug 2008 13:28:04 -0700, Keith Thompson wrote:
santosh <sa*********@gmail.comwrites: [...]
> A conforming implementation could insert it's own main
and invoke man from it.

An implementation is specifically forbidden to declare a prototype for
main (C99 5.1.2.2.1p1); that includes a prototype that's part of a
definition. Conceivably an implementation could provide a
non-prototyped definition, but that would be silly.
I suspect 5.1.2.2.1p1 is meant to allow both
int main(void)
and
int main(int, char *[])
where one or the other would be rejected if the implementation predeclares
main with a prototype. If santosh meant that an implementation can insert
its own main function as if it's defined in a separate translation unit,
then its effect is identical whether the definition includes a prototype
or not, and since the unprototyped version is not forbidden, the as-if
rule also allows the prototyped version.
Aug 6 '08 #20
Keith Thompson wrote:
santosh <sa*********@gmail.comwrites:
[...]
>>Eric Sosman wrote:
[...]
>>> For example, how would you describe the error in

#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}

? (Yes, this is a trick question.)
[...]
>Just to followup, many knowledgeable members of this group have
previously said that an implementation is not required to reject the
translation of any program that does not contain a selected #error
directive.

Right.
>In light of that I would amend my answer above and say that
no error need be emitted by a compiler for the translation unit given
above by Eric.

Compilers don't emit errors; they emit diagnostic messages.
Yes.

<snip>
>A conforming implementation could insert it's own main and invoke man
from it.

An implementation is specifically forbidden to declare a prototype for
main (C99 5.1.2.2.1p1); that includes a prototype that's part of a
definition. Conceivably an implementation could provide a
non-prototyped definition, but that would be silly.
Ah, OK.
On the other hand, some tool in the environment (that's not considered
part of the C implementation) could always provide a definition for
main. Typically that tool is a text editor that you use to write your
own definition of main, but it could be something else.
Right. The post was just a bit of nitpicking, and it appears that I'm
not up to scratch yet. :-)

Aug 7 '08 #21
On Aug 6, 9:41 pm, "Mark B [Diputsur]" <diput...@gmail.comwrote:
"Huibert Bol" <huibert....@quicknet.nlwrote in message

news:g7**********@registered.motzarella.org...
Eric Sosman wrote:
For example, how would you describe the error in
#include <stdio.h>
int man(void) {
return puts ("Hello, world!\n") == EOF;
}
? (Yes, this is a trick question.)
It prints an additional newline ;-)

Doubtful it will print anything...
it's missing the function called at program startup.
What are you talking about?
Aug 7 '08 #22

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
4700
by: Todd | last post by:
I'm getting what I think is a very strange result in ASP.NET. I have code as follows inside a method: string tempCol = "1"; string tempStr = "2"; My code wasn't working properly so I stepped...
5
3033
by: code_wrong | last post by:
Hi Firefox does not support the IE specific 'event' identifier and just quits running the script. ..... even though the identifier only turns up in code marked for IE only ... Does this seem...
7
2169
by: Kobu | last post by:
The code below isn't compiling for me (error message: conflicting types for 'total' - pointing to the extern declaration). Why wouldn't this work, since the types are different, the extern...
1
4017
by: Acken | last post by:
Hi i have spent almost 2 days on these now..and cannot figure out what is wrong?! It seems so simple and innocent , but it is stumbling a novice of me. Please help to point out anything wrong and...
9
1486
by: nomadcontauroi | last post by:
iam wondering if a function name,say sum,could serve as an identifier? thanks.
10
1850
by: John Salerno | last post by:
Here's a sentence from Learning Python: "Names not assigned a value in the function definition are assumed to be enclosing scope locals (in an enclosing def), globals (in the enclosing module's...
17
2681
by: Rico | last post by:
Hello, I am in the midst of converting an Access back end to SQL Server Express. The front end program (converted to Access 2003) uses DAO throughout. In Access, when I use recordset.AddNew I...
10
11760
by: teddarr | last post by:
I am trying to construct a class with several functions and identifiers. The identifier in question is static double AIR which will hold the value of the annual interest rate in the class. I have...
3
2715
by: parag_paul | last post by:
hi All for the following #include <stdio.h> typedef struct{ int a ; int b; char* j; } AST;
0
1419
by: Gordon Burditt | last post by:
>----------------------------- 8< ---------------------------------- Not if you include <string.h>, in which case the second paragraph above is an issue. Otherwise, it's OK. It's OK, but I...
0
7121
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
6993
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7162
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7375
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
4899
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4584
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3088
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3078
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
650
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.