[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
>    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.


More information about the llvm-dev mailing list