<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/120108>120108</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [clang][modules] Inline function incorrectly marked as hidden leads to undefined reference
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang,
            clang:modules
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ldionne
      </td>
    </tr>
</table>

<pre>
    In some circumstances, functions are incorrectly given hidden visibility when Clang modules are enabled, which leads to undefined references. Here's a reproducer where we basically have two small header files, each of which is a module:

```c++
// construct_at:
template <class T>
constexpr void __construct_at(T* location, T arg) {
  void* loc = __voidify(*location);
 (void)loc;
}
```

```c++
// voidify
template <class T>
__attribute__((__always_inline__)) void* __voidify(T& from) {
  return const_cast<void*>(static_cast<const volatile void*>(&from));
}
```

We then have a small test program that uses `construct_at`:

```c++
#include <construct_at.h>

void foo(int* ptr) {
    __construct_at(ptr, 3);
}
```

Finally, we compile with modules enabled:

```
clang++ -std=c++17 -fmodules -fcxx-modules -fmodules-cache-path=ModuleCache.noindex -fbuiltin-module-map -c test.cpp -o test.o
```

And we can see that an undefined reference to `__voidify` is being generated in `test.o`, which should never happen for a few reasons:
1. It's a template, so we need to have a `linkonce_odr` definition in `test.o`
2. Even worse, it's marked as `always_inline` so it's absolutely evident that this can't end happily. Indeed, we know at the declaration that a definition will never be emitted anywhere else, so this is bound to fail.

In other words, this shouldn't create an undefined reference to `__voidify` regardless of whether that function is marked as `__always_inline__`, but it's just a bit more vexing that it does.

[Full reproducer](https://github.com/user-attachments/files/18153807/reproducer.zip) attached.

Also tracked as rdar://121551667.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyMVk9vq7oT_TTOZgQCkwBZZJEmN_p18dtVektk7CH41tjINknzPv2TDWlS9arvSUgN7vw7Z2YOZs7Js0bckc0L2RxXbPK9sTslpNEaV60Rt92rBmcGBC4tnwbnmeboCD1AN2nupdEOmEWQmhtrkXt1g7O8oIZeCoEaLtLJVirpb3DtUcNBMX2GwYhJ4eyKmrUKRYh57SXvQSETDryBSQvspEYBFju0GFKn8D-0SGjlgIHF0RoxcbQhuEW4IrTMSc6UukHPLgj-asANTCnokQm00Ek1A0DGezDdklSGeHNZpNiTLD5lNj-c0JfwZHtCT4SegBvtvJ24b5ifzT0Oo2IegRQHrphz8EaKXyTbR1P8GC1cjBTQNF98af1G6B6U4SyQGep6A2bPhG6BVCEjRL_FCEhxhKYJJ7K7EVoTun_4bkkRPQitZ5-tMnw-I9XxGdC_4bsn-AFX0zDvrWwnj00TK6mbhqkru7lGaiV1PN4GIHcAz4W_EVpCZ83wjNSin6ye2W04c54Uh8U5JKW188xLfv9XtIOLUcxLhfDFktByif7Jyx85-AvBh7mMw8KWUfHoPIzWnC0bwPfMw-TQQWDquXll9vOoFFJzNYmZuyfHtJ8pJNk-zkRnDKG11D6QNHr7TAl8n5hocYDiZ2AnqcMWxLVC4GYYA0dX6fvP7btv3jcQYWzDns5YIHFekOK4QMsrSLp7iKTjHx_J4235lXDGe0xG5ntSHP8fDw_hKNVGaoEfkHTtJJWXenFOBjZCwiP1KR9HSMz823yHttciYmIaHOLcIKb_JBdBRUiZPQavzMKmtyj1Gc6o0TKPAqQOVku6MntIkevNpARovKCFno0jauiMBQYdXsEic0a7mb88hVe_6NJ9aUIgZ0KtGlGEYpYxI2WmpH43mmNjhA1lxdplWORv5WR7msKvIKpXY12MKudUA7PvKIDF2fyyfCGkM3c71jqjJo_qBniRArWfWfO9dIFHQisPqEXEKNUthVctcBFlhHdtrhDNEQRyxWxUnIX559KvUqmFrhYBB-kDv0zfZn1G5e6kxNShF2bSkZqOSZXODX7VYHwfVN1YEcU6Ws_dmIvlFoMq_fe2WzwzKxQ6N4s-xgQRwf1TFsr5wuh3QZuHo538ndnfkwsUtNLDYCzCBT_CbMW40oMw6BZQZPNympR6-miRzZHQuvd-jDMUpfcsfT-1KQ_SdZoc2oR5z3g_oPaO0NPy-Trldb4p6qwi9PQImP4txyAeswuKJfNeBb4t4wsyK5j9TJjTfLPJy7JKV2JXiG2xZSvc5VWxLspyW-erfrde002WZ1XVtlW2XWdbXmy7vKV0XYiyFt1K7mhG1znNy7wsSpqlVY1VxWqGLWuLdrsm6wyH0F-lLkNq7HklnZtwl9Msz-qVYi0qF68hlC7KQwk9fL4V-0VYwvnmuLK7EChpp7Mj60xJ590jtJdexTvN7Ls5ks3L3X1zhNfYy6emP11dHt1fri8_3UVWk1W7H7oXClr-JKM1v5F7Qk8ReOzgjP2yo_8EAAD__-_UFPA">