<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 - Lack of visibility specification on forward declaration of class template may hide derived symbols"
href="https://bugs.llvm.org/show_bug.cgi?id=48360">48360</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Lack of visibility specification on forward declaration of class template may hide derived symbols
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Windows NT
</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>C++
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>predelnik@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, dgregor@apple.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>Take a look at the following program
#include <any>
template <typename T>
class PublicTemplateClass;
class [[gnu::visibility("default")]] D {};
class E
{
PublicTemplateClass<D> f ();
};
template <typename T>
class [[gnu::visibility("default")]] PublicTemplateClass
{
};
PublicTemplateClass<D> E::f ()
{
PublicTemplateClass<D> v;
std::any a (v);
return v;
}
Running the following command:
clang++ -fvisibility=hidden -std=c++17 -shared -fPIC a.cpp && readelf -s a.out
| grep Manager
I see the following output:
15: 0000000000001c70 39 FUNC LOCAL HIDDEN 12
_ZNSt3any17_Manager_inter
16: 0000000000001b90 178 FUNC LOCAL HIDDEN 12
_ZNSt3any17_Manager_inter
Manager...thingie is basically a function pointer which is compared in any_cast
in libstdc++. So the problem is that when it's hidden any_cast to correct type
will fail because user of the library will have different pointer to this
function.
If however I add [[gnu::visibility("default")]] to forward declaration of
PublicTemplateClass like this:
template <typename T>
class [[gnu::visibility("default")]] PublicTemplateClass;
I receive the following:
10: 0000000000001ef0 178 FUNC WEAK DEFAULT 12
_ZNSt3any17_Manager_inter
13: 0000000000001fd0 39 FUNC WEAK DEFAULT 12
_ZNSt3any17_Manager_inter
28: 0000000000001fd0 39 FUNC WEAK DEFAULT 12
_ZNSt3any17_Manager_inter
29: 0000000000001ef0 178 FUNC WEAK DEFAULT 12
_ZNSt3any17_Manager_inter
I'm not 100% sure that this is not intended behavior but this seems to be very
unfortunate because:
1. Error is very subtle, hard to find, runtime only &c.
2. gcc does not behave like this
3. Normal classes do not seem to trigger such behavior with requiring
visibility specification for forward declarations.
If you need me to built full fledged example where executable + so lib fail to
perform any cast in such case I would be happy to provide that but I hope the
problem is already clear from this short sample.</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>