Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Feb 1997 18:34:51 -0700 (MST)
From:      Terry Lambert <terry@lambert.org>
To:        chuckr@glue.umd.edu (Chuck Robey)
Cc:        terry@lambert.org, jmacd@CS.Berkeley.EDU, hackers@freebsd.org
Subject:   Re: g++, STL and -frepo on FreeBSD-2.2-Beta
Message-ID:  <199702050134.SAA13752@phaeton.artisoft.com>
In-Reply-To: <Pine.OSF.3.95q.970204193602.1349B-100000@baud.eng.umd.edu> from "Chuck Robey" at Feb 4, 97 07:40:51 pm

next in thread | previous in thread | raw e-mail | index | archive | help
> Terry, I'm not sure you're right.  The virtual tables show up (using nm on
> the obj files) as "t" objects, not "T", meaning local text objects.  The
> way I understand from JW Eaton, under Linux (where he wrote it natively)
> the symbols in the obj files for these virtual tables instatiated for
> templates are global, not local.  There is one of these tables made for
> each template type, correctly, but they're coming up local.  This seems to
> be to point to an error source in the compiler, not the linking process.
> 
> FWIW, the symbols make it into the library, but as local symbols, not
> global.  Am I confused about this?

Well... you are, or I am.  8-).

Riddle me this: if the compiler makes a 't' reference to a real 'T'
somewhere... how can it generate the real 'T'?  It can't just pick
one of the files at random an put it there.  I might be compiling
incrementally.


EXAMPLE: Say I have TFifoQ.h:

	template <class Type>
	struct FifoQueueElement {
		friend class FifoQueue<Type>;
	private:
		const Type		*m_pItem;
		FifoQueueElement<Type>	*m_pNext;
	};


	template <class T>
	class FifoQueue
	{
	private:
		FifoQueueElement<Type>	*m_head;
		FifoQueueElement<Type>	*m_tail;
	public:
		void Insert( const Type *pItem);
		Queue() { head = tail = NULL; }
	};

	template <class Type>
	void
	FifoQueue<Type>::Insert( const Type *pItem)
	{
		FifoQueueElement<Type> *pQE = new FifoQueueElement<Type>;

		pQE->m_pItem = pItem;
		pQE->m_pNext = NULL;
		if( m_tail == NULL)
			m_head = pQE;
		else	m_tail->pNext = pQE;
		m_tail = pQE;
	}

and I have foo.cc:

	#include "TFifoQ.h"

	// instantiate global int queue using template...
	Queue<int>	foointqueue;

	... stuff ...

and I have fee.cc:

	#include "TFifoQ.h"

	// instantiate global int queue using template...
	Queue<int>	feeintqueue;

	... stuff ...

...do you expect the code to implement the Insert method for a FifoQueue
of int to go into foo.o or fee.o?

Here's what I expect:

a.out:
---------
Personally, I expect it to be generated static in *both* of them, with
no global reference, in the a.out case.  Anything else is an error.  If
you run a new g++ with the a.out ld for FreeBSD, it's pilot error.

Alternately, you could have a compiler flag that was applied to
fee..  that said "don't generate code for templates" so it only
made a reference, and you would *not* use that flag when compiling
foo.cc so it would generate the real thing.  Then, when you linked,
there would be one instance and multiple references.  If you used
the flag on everone who actualized the template class by instantiating
it, you wouldn't get a real instance of the code.  Again, you'd be
guilty of pilot error.


ELF:
---------
In the ELF case, I expect it will either do waht a.out does, OR if
they were clever and used ELF for what it is good for, it will
generate the template instance for an queue of integers in *both*
fee.o and foo.o, *BUT* in different ELF segments than the rest of
the code in foo.o and fee.o, and then when it links, it will bring
in only once (probably from whichever is first in the linker argument
list).

Alternately, you *could* have the same compiler flag for ELF, too,
and have the same possibility for pilot error, while creating only
a single instantiation at compile time.


Godlike compiler writer magic:
---------
If, on the other hand, they were truly *godlike*, they would provide
a method of implementing a precompiled template instantiation, and
generate one of those an an object file.  Inside, it would use RTTI
(run time type identification) to decide what kind of object it was
referring to, and the compiled template code would not enforce the
object type.  The compiler would compile fee.cc and foo.cc, and
*not* generate the code for the template.  But it would rigidly
enforce *at compile time* type checking *as if it had*.  Then, when
it generated any references for the "FifoQueue of int's" public
member functions or data, it would generate them *without* the
linker glue for link time type checking, and rely solely on the RTTI
to enable the class to "do the right thing".


I find this last one extremely unlikely.  But if they are doing it,
then the symbols are right, I am wrong.  And it's still pilot error,
since if ther pilot did the right thing, there would be: (1) an object
module with the type-stripped class instance, (2) multiple object
modules with refernces to the type stripped references, and (3) an
RTTI interface, which I don't believe currently exists in a form
suitable for use in doing this sort of thing by hacking up the compiler
for the special case where it is compiling a template file to generate
an object with type-non-specific 'this' and private member data
references.


---------

If I'm wrong (the declaration didn't need to be in scope), then
it's probably that they are incorrectly applying the "don't generate
template" flag when they shouldn't be, not creating a template
instance object seperate from the rest of their objects, like they
should be, or relying on linker tricks which require multiple
instantiations to be coalesced to a single instance, which the a.out
linker is too stupid to do, and the ELF linker is probably currently
too stupid to do, even though ELF could support it.

Feel free to correct me, though... I'd rather know the right answer
than just think I knew the right answer.  If there's another way for
me to be wrong, let me know.


					Regards,
					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702050134.SAA13752>