[LLVMdev] r72619
Bill Wendling
wendling at apple.com
Fri Dec 4 12:56:35 PST 2009
On Dec 4, 2009, at 12:53 PM, Bill Wendling wrote:
> 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.
Addendum: We don't take the "goto" in the "original" case and in ToT
because of r51655. However, r72619 is what's triggering ToT to
generate the bad instantiations that Doug talks about.
-bw
More information about the llvm-dev
mailing list