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

Reply via email to