I've been looking at PR23708, where a non-inline explicitly
specialized template function is inheriting the inline semantics of
the inline member function it specializes, when using pre-compiled
headers (whew). This can be seen in the following example:
template <class T> class simple_class {
public:
inline void testfn (T);
};
template <> void simple_class<int>::testfn (int) {} //
incorrectly inheriting 'inline' semantics when using PCH
Where the specialization function ends up in a COMDAT section.
I have some understanding on why this is happening, but could use a
little help in fixing the problem. If I compile the example above
into a precompiled header, the sequence of events is as follows:
simple_class<T>::testfn is generated
simple_class<T>::testfn is assigned to the COMDAT section by
note_decl_for_pch()
simple_class<int>::testfn (implicit instantiation) is generated,
which inherits the COMDAT-ness from simple_class<T>::testfn
simple_class<int>::testfn (explicit specialization) is generated
simple_class<int>::testfn (explicit specialization) is assigned to
the COMDAT section by duplicate_decls(), when it merges the
declarations with the implicit instantiation
When not using precompiled headers, the sequence is this:
simple_class<T>::testfn is generated
simple_class<int>::testfn (implicit) is generated
simple_class<int>::testfn (explicit) is generated
simple_class<T>::testfn is assigned to the COMDAT section
simple_class<int>::testfn (implicit) is assigned to the COMDAT
section
My first approach was to modify duplicate_decls() so it wouldn't copy
the COMDAT-ness into the explicit specialization, the same way that
we avoid copying the DECL_DECLARED_INLINE_P. This worked for my
particular instance, however because COMDAT implementation is host-
dependent, it seems very dangerous.
My second approach is to disable the code in note_decl_for_pch() that
assigns COMDAT-ness early. This works, too, but it would be nice to
not lose the advantage that this code was put in for.
So, my third approach was to modify note_decl_for_pch() to filter out
simple_class<T>::testfn, similarly to how the implicit <int>
declaration is filtered out. However, in order to do so, I need to
detect that simple_class<T>::testfn is a member function of a
template class. But how do I do this? I can detect which class the
function is a member of by looking at DECL_CONTEXT, but I don't see
how to determine if this class is a template class. Is there a way
to find the class type tree from the FUNCTION_DECL? I can get see
the type information I want at DECL_CONTEXT(decl)->common.chain in
the debugger, but I have no reason to believe that this is the
correct way to get it, or that it will work all of the time.
Does anyone have any suggestions on:
a) whether I'm headed in the right direction, and
b) if so, how to determine that simple_class<T>::testfn is a member
of a template class, and not an instantiated class?
Thanks -
Josh