[comp.std.c++] Blocks, scopes and declaration statements

shankar@hpclscu.HP.COM (Shankar Unni) (10/16/90)

Does a declaration in the middle of a { } block start a new scope? A new
block?

Consider the following example:

   void foo()
   {
       extern void bar();	// decl
       int i;			// decl
       
       i = 1;			// statement

       extern void bar(int);	// decl: overloaded with above bar()?
       
       bar();			// statement: legal?
   }

Is the second declaration of bar ("extern void bar(int)") considered an
overloaded variant of the parameterless bar(), or the start of a new scope
(so that it hides the parameterless bar())?

Cfront 2.1 (and 2.0) apparently seems to make the latter interpretation,
and complains about the parameterless call to bar().

The ARM (sections 7, 10.4, etc) is suitably obscure on this point. They do
mention that declarations hide other declarations of the same identifier in
"an outer block", but it's unclear as to how that is to be applied in the
above situation.

Anyone care to comment?
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard California Language Lab.     Internet: shankar@hpda.hp.com
Phone : (408) 447-5797                           UUCP: ...!hplabs!hpda!shankar

bs@alice.att.com (Bjarne Stroustrup) (10/17/90)

A declaration statement does not start a new block. Your example is legal.

ellis@tekchips.LABS.TEK.COM (Cynthia Ellis) (10/17/90)

In article <77210008@hpclscu.HP.COM> shankar@hpclscu.HP.COM (Shankar Unni) writes:
>Does a declaration in the middle of a { } block start a new scope? A new
>block?
>
>Consider the following example:
>
>   void foo()
>   {
>       extern void bar();	// decl
>       int i;			// decl
>       
>       i = 1;			// statement
>
>       extern void bar(int);	// decl: overloaded with above bar()?
>       
>       bar();			// statement: legal?
>   }
>
>Is the second declaration of bar ("extern void bar(int)") considered an
>overloaded variant of the parameterless bar(), or the start of a new scope
>(so that it hides the parameterless bar())?

Per E&S (section 6.3), a block is equivalent to a compound statement,
which is a statement-list. A statement-list is then composed of a
statement, or a statement-list followed by a statement. It is explicitly
stated at end of the section that a declaration _is_ a statement (section
6.7). And, in section 6.0, E&S explicitly states that "... in C++ 
declarations need not be placed before statements in a block, but can be 
introduced where first needed".

>Cfront 2.1 (and 2.0) apparently seems to make the latter interpretation,
>and complains about the parameterless call to bar().

Somehow this must be some sort of scope definition bug in cfront2.0
(AT&T has some problem with our cfront2.1 upgrade paperwork, so I don't 
have 2.1 to test against yet). If you move the second extern void bar 
declaration so that it is before the "i = 1;" statement, the code compiles! 
So cfront2.0 must be tacitly assuming that the second bar declaration _does_
start a new block, which is (at least to me) in conflict with the excerpts 
of E&S section 6 quoted above.

>The ARM (sections 7, 10.4, etc) is suitably obscure on this point. They do
>mention that declarations hide other declarations of the same identifier in
>"an outer block", but it's unclear as to how that is to be applied in the
>above situation.

By how I read E&S, this should all be in the same block, which means that
the overriding argument should not apply here.


Cynthia Ellis
Tektronix, Inc.
ellis@tekcrl.LABS.TEK.COM
(503) 627-6680

jimad@microsoft.UUCP (Jim ADCOCK) (10/19/90)

In article <77210008@hpclscu.HP.COM> shankar@hpclscu.HP.COM (Shankar Unni) writes:
|Does a declaration in the middle of a { } block start a new scope? A new
|block?
|
Consider your example, slightly rewritten:

void foo()
{
    extern void bar();
    // int i; i=5;
    extern void bar(int);
    bar();
    bar(5);
}

Introduce the int i line, and it fails to compile on the compiler mentioned.

|Is the second declaration of bar ("extern void bar(int)") considered an
|overloaded variant of the parameterless bar(), or the start of a new scope
|(so that it hides the parameterless bar())?
|
|Cfront 2.1 (and 2.0) apparently seems to make the latter interpretation,
|and complains about the parameterless call to bar().

Without the intervening "int i" line, it compiles.  So, if anything,
the compiler is interpreting the "int i" line as the start of the new
scope.  But even if it *is* the start of a new scope, shouldn't both
bars still be accessible?

|The ARM (sections 7, 10.4, etc) is suitably obscure on this point. They do
|mention that declarations hide other declarations of the same identifier in
|"an outer block", but it's unclear as to how that is to be applied in the
|above situation.

Even if a new scope is being introduced, I still would not expect the
"outer" bar to be hidden by the "inner" bar with a different parameter
list.  And, I think introducing a new declaration or definition or
executable statement should not introduce a new "hidden" scope.  To
do so defeats the idea that in C++ you should be able to intoduce a new
variable where first used -- because to do so then introduces a hidden
scope that can cause the meaning of some variables already written to 
change.  Example: consider editing a large existing foo function having
within it the same bar declarations and usages as above.  In modifying
the existing function you introduce the "int i; i=5" statement in the
middle of the routine.  All of a sudden distant parts of foo fail to 
compile.

So I believe introducing a new variable in a routine does not start a new
scope, and both bar() and bar(int) should remain accessible even if there
were an intervening new scope introduced.

I'd be tempted to call this a compiler limitation, rather than a language
definition issue.

[standard disclaimer]