Topic: block scope extern declarations
Author: scott douglass <sdouglass@arm.com>
Date: 2000/07/15 Raw View
The Standard, in section 3.5, says:
> 6 The name of a function declared in block scope, and the name of an
object declared by a block scope
> extern declaration, have linkage. If there is a visible declaration of
an entity with linkage having the
> same name and type, ignoring entities declared outside the innermost
enclosing namespace scope, the block
> scope declaration declares that same entity and receives the linkage of
the previous declaration. If there is
> more than one such matching entity, the program is ill-formed.
Otherwise, if no matching entity is found,
> the block scope entity receives external linkage.
>
> [Example:
>
> static void f();
> static int i = 0; // 1
> void g() {
> extern void f(); // internal linkage
> int i; // 2: i has no linkage
> {
> extern void f(); // internal linkage
> extern int i; // 3: external linkage
> }
> }
>
> There are three objects named i in this program. The object with
internal linkage introduced by the declaration
> in global scope (line // 1), the object with automatic storage duration
and no linkage introduced by
> the declaration on line // 2, and the object with static storage
duration and external linkage introduced by
> the declaration on line // 3. ]
I'm reading the bit that says "Otherwise, if no matching entity is found,
the block scope entity receives external linkage." as meaning the same as
"Otherwise, if there is no visible declaration of an entity with linkage
having the same name and type, ignoring entities declared outside the
innermost enclosing namespace scope". The point being that, in the example
given, the 'i' on line // 2 doesn't count as a "matching entity".
If I understand what I've quoted then the 'i' on line // 3 would have to be
defined in another translation unit, for example:
int i = 3;
The standard seems to be requiring something that I would expect to be
impossible in all the implementations I'm familiar with; namely that the
'i' on line // 1 is a different object than the 'i' on line // 3.
And to check my understanding further, if I alter the example slightly:
void fn(bool);
static int i = 0; // 1
void g() {
int *p = &i; // that's the 'i' on line // 1
int i; // 2: i has no linkage
{
extern int i; // 3: external linkage
fn(&i == p);
}
}
Then 'fn' will always be called with false because the 'i' on line // 1 is
a different object than the 'i' on line // 3.
My questions are:
1 -- Is this implementable in practice? Do object file formats really
allow two distinct objects named 'i' one static and one an extern
reference? [Well, I guess the static 'i' doesn't have to be given a name
(and since there are no tentative statics in C++ I can't even construct a
forward reference example where it would be handy) but the implementations
I'm familiar with do give names to the statics.]
2 -- What happens if I add another one?
void g2() {
int i; // 4: i has no linkage
{
extern int i; // 5: external linkage
}
}
Now, is the 'i' on line // 5 the same as the 'i' on line // 3 or on line //
1? If you answer "yes", please justify from the standard. If you answer
"no", do you believe any real implementation can distingusih between the
'i' on line // 3 and the 'i' on line // 5?
I think the following case is similar:
struct T { int i; void g3(); };
void T::g3() {
extern int i; // 6: external linkage (the member 'i' prevents all
'i's with linkage from being visible)
}
In short: How can this part of the Standard be reasonably implemented?
or: Do I (and the example in the Standard) misunderstand?
A brief glance at the Jan 99 draft of C99 seems to have the same problem.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: wmm@fastdial.net
Date: 2000/07/15 Raw View
In article <4.3.2.7.2.20000714142102.00b2afc8@mail1>,
scott douglass <sdouglass@arm.com> wrote:
> The Standard, in section 3.5, says:
> > 6 The name of a function declared in block scope, and the name of
an
> object declared by a block scope
> > extern declaration, have linkage. If there is a visible
declaration of
> an entity with linkage having the
> > same name and type, ignoring entities declared outside the
innermost
> enclosing namespace scope, the block
> > scope declaration declares that same entity and receives the
linkage of
> the previous declaration. If there is
> > more than one such matching entity, the program is ill-formed.
> Otherwise, if no matching entity is found,
> > the block scope entity receives external linkage.
> >
> > [Example:
> >
> > static void f();
> > static int i = 0; // 1
> > void g() {
> > extern void f(); // internal linkage
> > int i; // 2: i has no linkage
> > {
> > extern void f(); // internal linkage
> > extern int i; // 3: external linkage
> > }
> > }
> >
> > There are three objects named i in this program. The object with
> internal linkage introduced by the declaration
> > in global scope (line // 1), the object with automatic storage
duration
> and no linkage introduced by
> > the declaration on line // 2, and the object with static storage
> duration and external linkage introduced by
> > the declaration on line // 3. ]
>
> I'm reading the bit that says "Otherwise, if no matching entity is
found,
> the block scope entity receives external linkage." as meaning the
same as
> "Otherwise, if there is no visible declaration of an entity with
linkage
> having the same name and type, ignoring entities declared outside the
> innermost enclosing namespace scope". The point being that, in the
example
> given, the 'i' on line // 2 doesn't count as a "matching entity".
Yes, that's what is intended.
> If I understand what I've quoted then the 'i' on line // 3 would have
to be
> defined in another translation unit, for example:
> int i = 3;
Right.
> The standard seems to be requiring something that I would expect to
be
> impossible in all the implementations I'm familiar with; namely that
the
> 'i' on line // 1 is a different object than the 'i' on line // 3.
I'll come back to "impossible" shortly, but that is what
was intended.
> And to check my understanding further, if I alter the example
slightly:
>
> void fn(bool);
> static int i = 0; // 1
> void g() {
> int *p = &i; // that's the 'i' on line // 1
> int i; // 2: i has no linkage
> {
> extern int i; // 3: external linkage
> fn(&i == p);
> }
> }
>
> Then 'fn' will always be called with false because the 'i' on line //
1 is
> a different object than the 'i' on line // 3.
Correct.
> My questions are:
> 1 -- Is this implementable in practice? Do object file formats
really
> allow two distinct objects named 'i' one static and one an extern
> reference? [Well, I guess the static 'i' doesn't have to be given a
name
> (and since there are no tentative statics in C++ I can't even
construct a
> forward reference example where it would be handy) but the
implementations
> I'm familiar with do give names to the statics.]
Implementations are free to name things at the link level
whatever they wish. This is commonly used to implement "type-
safe linkage," where the name of a function is "mangled" by
adding an encoded version of its signature to the name (which
need not even match the source spelling of the name, and
usually doesn't for things like constructors, destructors,
and operator functions).
There's no requirement that the link-level naming scheme be
the same for entities with external linkage and internal
linkage. Thus the name of the static "i" might be given to
the linker as something like __foo_cpp_static_i (if defined
in file "foo.cpp") and the external one might be simply _i.
(This is an example, of course; there's no requirement that
names be encoded at all, if there is another mechanism for
achieving the same result. A linker with sophisticated
attributes could, for instance, call both entities "i" and
keep them separated by their associated attributes.)
> 2 -- What happens if I add another one?
>
> void g2() {
> int i; // 4: i has no linkage
> {
> extern int i; // 5: external linkage
> }
> }
>
> Now, is the 'i' on line // 5 the same as the 'i' on line // 3 or on
line //
> 1? If you answer "yes", please justify from the standard. If you
answer
> "no", do you believe any real implementation can distingusih between
the
> 'i' on line // 3 and the 'i' on line // 5?
I didn't understand how to transform this question into a
yes/no response. However, I don't see any difference
between lines 3 and 5 -- both refer to some entity with
external linkage defined somewhere else, and since there can
be only one such entity in a program, 3 and 5 are the same.
> I think the following case is similar:
>
> struct T { int i; void g3(); };
> void T::g3() {
> extern int i; // 6: external linkage (the member 'i'
prevents all
> 'i's with linkage from being visible)
> }
Yes, I'd agree with this as well.
> In short: How can this part of the Standard be reasonably
implemented?
> or: Do I (and the example in the Standard) misunderstand?
This is what was intended. I don't see any problem with
implementing it.
> A brief glance at the Jan 99 draft of C99 seems to have the same
problem.
Yes -- the reason C++ is this way is because C89 was that way,
and we didn't see a compelling reason to break compatibility
(although I think I'm safe in saying that most of the C++
Committee members dislike block-scope externs).
--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]