[comp.lang.c++] Linkage & a question on name mangling

rfg@ics.uci.edu (Ron Guilmette) (12/23/89)

In article <1545@aber-cs.UUCP> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes:
>
>    Anyway, many people have now corrected me regarding the C++ default linkage
>    for const objects.
>
>This is really being a language lawyer, but: linkage != storage class.  From
>what I understand, const implies by default the *storage class* static; this
>in turn, at file scope, implies local linkage. To see the difference,
                         ^^^^^^^^^^^^^^^^^^^^^

*This* is really being a language lawyer, but note that the two concepts
are strongly related.

>consider const entities local to a block; is their default storage class
>"auto" or "static"? To me it is "static" in C++ (and "auto" in Ansi C), even
>if linkage only really makes sense at file scope level.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

More language lawyering.  This is *not* true in cases where you have nested
things declared `extern'.

>Just to show off: how many of you did know that "typedef" technically is a
>storage class in C (and C++),

Not me, but then that is just a syntactic convenience which should be invisible
to the user if proper semantic errors are being produced.

>and that 'extern "C"' does *not* imply
>the "extern" storage class, because it is not a storage class?

But it *does* (at least partially).  In 7.4: "Otherwise, a function
declared in a linkage specification behaves as if it was explicitly
declared `extern'".

>Does it matter that 'extern "C"' is not a storage class ? YES!  for example,
>both of these are accepted gleefully by GNU C++ (and correctly, I believe):
>
>	extern "C" typedef int algebraic; /* correct, but somewhat pointless */

Perhaps there is some point to such a construct if your debugger has enough
smarts to know about typedef names, but is also to dumb to know about
C++ name mangling.

>Notice that since mangling does not apply to variable names yet...

Yes.  Can somebody please tell me why that is the case?  It seems to me that
all of the "type checking" effects that are squeezed out of the linker via
name mangling function names would be equally applicable to the problem
of assuring that the types of variables and (extern) const's were consistant
across object files.  What's the story?

>I think that Ron Guilmette (I remember he being the author) has a few new/old
>interesting test cases to add to his fine C++ test suite... And a little more

You can be sure that I've squirrled your posting away for inclusion at
some future point Peter.

// rfg

pcg@rupert.cs.aber.ac.uk (Piercarlo Grandi) (12/26/89)

In article <259312BD.11972@paris.ics.uci.edu> rfg@ics.uci.edu (Ron Guilmette) writes:

   >and that 'extern "C"' does *not* imply
   >the "extern" storage class, because it is not a storage class?

   But it *does* (at least partially).  In 7.4: "Otherwise, a function
   declared in a linkage specification behaves as if it was explicitly
   declared `extern'".

Let me pick this nit: extern "C" per se does not; what happens is
that in C (and C++) function declarations have by default
storage class extern.

   >Notice that since mangling does not apply to variable names yet...

   Yes.  Can somebody please tell me why that is the case?  It seems to me that
   all of the "type checking" effects that are squeezed out of the linker via
   name mangling function names would be equally applicable to the problem
   of assuring that the types of variables and (extern) const's were consistant
   across object files.  What's the story?

More or less like the problem with incorporating in a mangled procedure name
the return type: that duplicate declarations with different types result
in no error. Examples:

	extern int square(float);
	extern unsigned count = 0; /* in file a.C */

	extern float square(float);
	extern long signed count = 1L<<24; /* in file b.C */

If the "return type" is mangled in the name, the clash is not detected. For
variables this is especially poignant because C++ 2.0 forbids more than one
definition, even if they are uninitialized.

On the other hand, as I had indicated, with templates you
actually may *want* this to happen, because you can instantiate
procedures and classes over more than a type. Well, I have not thought
out the gory details, but I guess that some mangling will have to happen.


Given that we are into language lawyering :-> , here are some
more unsual, but well known ("admittedly the ice is thin here"
K&R) insecurities of C and C++ declarations:

    typedef signed;		/* 1 No name for this type. 		*/
    typedef unsigned weight;	/* 2 See later				*/
    extern struct fcb;		/* 3 fcb is just a struct		*/
    static;			/* 4 Unnamed int, local linkage		*/
    auto struct point {int x,y;}; /* 5 Struct declaration		*/
    register enum let {a,b,c};	/* 6 Enum declaration			*/
    register enum pound {one};	/* 7 Enum declaration			*/
    typedef point &pointref;	/* 8 A simple typedef			*/
    extern double let(let);	/* 9 What's this?			*/

    extern z(auto char)		/* 10 New in C++: unnamed argument	*/
    {
	weight;			/* 11 Unnamed variable, type weight	*/
	weight pound;		/* 12 Variable pound, type weight	*/
	auto;			/* 13 For good measure...		*/
	weight weight;		/* 14 Variable weight, type weight	*/
	point point;		/* 15 Legal in C++. Ugh!		*/
	register float;		/* 16 Unnamed variable			*/
	static fcb *fcb;	/* 17 What's this?			*/
	static pointref;	/* 18 But next is illegal		*/
	static point [1];	/* 19 Type is array of points		*/
	auto char (*)();	/* 20 Unnamed ptr to procedure		*/
	extern char (*)();	/* 21 Unnamed ptr to procedure		*/
    }

If you have slightly morbid tastes, try these with your friendly
C++ compiler (or, with some changes, a C compiler).  GNU C++ 1.35
behaves quite well; it does warn about empty declarations, but
there are some problems, at least for syntax. I have not tried to
assemble the resulting compiler output, but likely there are problems
there as well.

So, BUG REPORT for GNU C++:

	#21 breaks the compiler; #5, #6 and #7 have a funny storage class,
	and I *think* that it is illegal, even if ineffective. #9 gets
	a warning, but should probably be an error. #19 is faulted, but
	might be instead legal.

As usual, I wonder what would happen with cfront.

As usual, I think that typedef and enum don't mesh well with the
rest of C and C++, and that the ice has become too thin in too
many places. Well, an italian way of saying is

	"L'hai voluta la bicicletta? Adesso PEDALA!"

(Didn't you ask for a bicycle? Now WORK IT!)
--
Piercarlo "Peter" Grandi           | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcvax!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk

pkturner@cup.portal.com (Prescott K Turner) (12/27/89)

In article <259312BD.11972@paris.ics.uci.edu> rfg@ics.uci.edu (Ron Guilmette) w
rites:
> In article <1545@aber-cs.UUCP> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes:
> > ...
> >Notice that since mangling does not apply to variable names yet...
> 
> Yes.  Can somebody please tell me why that is the case?  It seems to me that
> all of the "type checking" effects that are squeezed out of the linker via
> name mangling function names would be equally applicable to the problem
> of assuring that the types of variables and (extern) const's were consistant
> across object files.  What's the story?

This was a conscious decision documented in Stroustrup's paper on type-safe
linkage at Usenix '88.  The difference between variables and functions is
that in most references to a function name, arguments are present which
neatly determine which overloaded alternative to call.  Consider a header
file which declares
   extern long count;
then in a file which includes this header a user declares
   int count;
   ...  // and refer to count:
   long i = count;
There are two ways to look at this that relate to name mangling:
   1. "count" is an overloaded variable name, and the user is going
      to get the variable declared long.
   2. "count" has inconsistent declarations.
Number 1 is unsatisfactory because this kind of example can surprise the user.
The paper doesn't find it worth discussing.

Number 2 is not supported by name mangling.  Since "long count" and
"int count" would have different mangled names, the linker would not
find the error in the program.
--
Prescott K. Turner, Jr.
Language Processors, Inc.
959 Concord St., Framingham, MA 01701 USA    (508) 626-0006 x232
UUCP: ...sun!cup.portal.com!pkturner    Internet: pkturner@cup.portal.com