[LLVMdev] r72619

Douglas Gregor dgregor at apple.com
Fri Dec 4 15:02:41 PST 2009


On Dec 4, 2009, at 2:40 PM, Eric Christopher wrote:

>>>
>> 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 :)


Clang has a specific function to determine whether an inline function  
should be externally visible (so that it will have strong linkage) or  
not (meaning that it should have available_externally linkage). It's  
FunctionDecl::isInlineDefinitionExternallyVisible() in tools/clang/lib/ 
AST/Decl.cpp. That covers the C case and GNU inline semantics in C++.

For C++, it's easier to distinguish: inline functions have external  
definitions unless they have an explicit template instantiation  
declaration (C++0x parlance for "extern template"); see  
GetLinkageForFunction in tools/clang/lib/CodeGen/CodeGenModule.cpp.

llvm-gcc will have to duplicate that logic to use available_externally  
properly.

	- Doug



More information about the llvm-dev mailing list