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>