<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Failing to dllexport class template member w/ explicit instantiation and PCH"
   href="https://bugs.llvm.org/show_bug.cgi?id=38934">38934</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Failing to dllexport class template member w/ explicit instantiation and PCH
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>7.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>hans@chromium.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>For example:

#ifndef IN_HEADER
#define IN_HEADER

template <typename T> struct S { };
extern template struct S<int>;

inline void use(S<int> *s, S<int> *t) {
  *s = *t;
}

#else

template struct __declspec(dllexport) S<int>;

#endif



$ clang -cc1 -triple i686-pc-win32 -fms-extensions -emit-pch
-building-pch-with-obj -o x.pch /tmp/x.cc
$ clang -cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm
-DUSE_PCH -include-pch x.pch -o - /tmp/x.cc

In the second invocation, S<int>::operator=(S<int>&) is supposed to get
emitted, but it's not because it appears as if its definition comes from the
PCH file and so would be emitted in the .obj file corresponding to the PCH.

However, it's just the declaration that's in the PCH, not the definition.


The code in ASTContext::DeclMustBeEmitted() is supposed to catch exactly this:

    bool IsExpInstDef =
        isa<FunctionDecl>(D) &&
        cast<FunctionDecl>(D)->getTemplateSpecializationKind() ==
            TSK_ExplicitInstantiationDefinition;

    if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef)
      return false;


However it doesn't work here because getTemplateSpecializationKind() returns 0,
as the function itself is not a template. At least that's what I think is
happening. It's seems I'm not understanding the AST right.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>