[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