echristo at apple.com
Fri Dec 4 14:40:52 PST 2009
> Only "_Z11dummysymbolv" should be there. Here's Doug's explanation of
> why this should be so:
> Here's what it *looks* like is happening, and where the FE is probably
> getting it wrong. First of all, the constructor in question is defined
> outside of the basic_string class template as a non-inline definition:
> template<typename _CharT, typename _Traits, typename _Alloc>
> basic_string<_CharT, _Traits, _Alloc>::
> basic_string(const _CharT* __s, const _Alloc& __a)
> Second, there is an explicit template instantiation declaration:
> extern template class basic_string<char>;
> That extern template instantiation declaration is supposed to suppress
> the implicit instantiation of non-inline member functions like that
> basic_string constructor. I had tripped over something similar to this
> previously, where the SL llvm-gcc was suppressing instantiation of all
> member functions of basic_string<char> (including inline ones, which
> would be a performance problem). So, there was clearly a change in
> this area.
> Here's my guess: We're not properly suppressing the implicit
> instantiation of non-inline member functions defined out-of-line.
> Thus, we're instantiating that basic_string constructor when we
> shouldn't be. That instantiation then forces the implicit
> instantiation of _S_construct<const char*>. Since _S_construct is a
> member template, it's instantiation is *not* suppressed (despite being
> in basic_string<char>), so we emit it as a weak definition.
> I don't have a debug llvm-gcc available to see why this might be
> happening. The logic to suppress instantiation based on an extern
> template is in instantiate_decl (gcc/cp/pt.c):
> /* Check to see whether we know that this template will be
> instantiated in some other file, as with "extern template"
> extension. */
> external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
> /* In general, we do not instantiate such templates... */
> if (external_p
> /* ... but we instantiate inline functions so that we can inline
> them and ... */
> && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
> /* ... we instantiate static data members whose values are
> needed in integral constant expressions. */
> && ! (TREE_CODE (d) == VAR_DECL
> && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
> goto out;
> For the basic_string constructor, if we don't take that "goto",
> something is wrong. If we do take that "goto", my guess is wrong. I
> don't have a recent debug llvm-gcc to validate my guess.
So, on top of this it seems like a lot of the semantics have changed after your patch. I'm certain the existing patch is wrong and that we'll want a computation somewhat similar to the clang one that I think Doug is going to post.
I think the safe thing is to revert for now and we can discuss all of the semantics and what's going on in a more leisurely fashion and let poor Bill get his project building :)
More information about the llvm-dev