<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><span class="vcard"><a class="email" href="mailto:andyg1001@hotmail.co.uk" title="Andy Gibbs <andyg1001@hotmail.co.uk>"> <span class="fn">Andy Gibbs</span></a>
</span> changed
<a class="bz_bug_link
bz_status_REOPENED "
title="REOPENED - instantiating a friend member specialization declaration does not look up member specialization properly"
href="https://bugs.llvm.org/show_bug.cgi?id=38883">bug 38883</a>
<br>
<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>What</th>
<th>Removed</th>
<th>Added</th>
</tr>
<tr>
<td style="text-align:right;">Resolution</td>
<td>FIXED
</td>
<td>---
</td>
</tr>
<tr>
<td style="text-align:right;">Version</td>
<td>5.0
</td>
<td>8.0
</td>
</tr>
<tr>
<td style="text-align:right;">Hardware</td>
<td>PC
</td>
<td>All
</td>
</tr>
<tr>
<td style="text-align:right;">CC</td>
<td>
</td>
<td>andyg1001@hotmail.co.uk
</td>
</tr>
<tr>
<td style="text-align:right;">Status</td>
<td>RESOLVED
</td>
<td>REOPENED
</td>
</tr></table>
<p>
<div>
<b><a class="bz_bug_link
bz_status_REOPENED "
title="REOPENED - instantiating a friend member specialization declaration does not look up member specialization properly"
href="https://bugs.llvm.org/show_bug.cgi?id=38883#c2">Comment # 2</a>
on <a class="bz_bug_link
bz_status_REOPENED "
title="REOPENED - instantiating a friend member specialization declaration does not look up member specialization properly"
href="https://bugs.llvm.org/show_bug.cgi?id=38883">bug 38883</a>
from <span class="vcard"><a class="email" href="mailto:andyg1001@hotmail.co.uk" title="Andy Gibbs <andyg1001@hotmail.co.uk>"> <span class="fn">Andy Gibbs</span></a>
</span></b>
<pre>The following (sadly not too minimal) code fragment was broken by commit
r350505:
/*******************************************************************/
#include <stdio.h>
struct Widget {
virtual ~Widget() = default;
virtual void doAction() const = 0;
template <typename X, typename... Args>
static Widget* Construct(Args... args) {
constexpr auto i = GetWidgetCtor<X>(0);
if constexpr (i != nullptr)
return i(args...);
else
return nullptr;
}
private:
template <typename X, auto Ret = WidgetCtor((X*)nullptr)>
static constexpr auto GetWidgetCtor(X* = nullptr) {
return Ret;
}
template <typename X>
static constexpr auto GetWidgetCtor(...) {
return nullptr;
}
};
template <typename... Args>
using WidgetGenerator = Widget*(*)(Args...);
template <typename X, typename... Args>
struct StandardWidget : Widget {
virtual void doAction() const override {
x.doAction();
}
private:
friend constexpr WidgetGenerator<Args...> WidgetCtor(X*) {
return [](Args... args){
return static_cast<Widget*>(new StandardWidget(X(args...)));
};
}
StandardWidget(X x) : x(x) { }
X x;
};
struct X1 {
friend constexpr WidgetGenerator<> WidgetCtor(X1*);
X1() { }
void doAction() const {
puts("X1::doAction");
}
};
struct X2 {
friend constexpr WidgetGenerator<int> WidgetCtor(X2*);
X2(int i) : i(i) { }
void doAction() const {
printf("X2::doAction with %i\n", i);
}
int i;
};
struct X3 {
friend constexpr WidgetGenerator<> WidgetCtor(X3*);
X3(double d) : d(d) { }
double d;
};
template struct StandardWidget<X1>;
template struct StandardWidget<X2, int>;
struct X3Widget : Widget {
virtual void doAction() const override {
printf("X3::doAction with %f\n", x.d);
}
private:
friend constexpr WidgetGenerator<> WidgetCtor(X3*) {
return [](){
return static_cast<Widget*>(new X3Widget());
};
}
X3Widget() : x(12.5) { }
X3 x;
};
void test() {
if (Widget* i = Widget::Construct<X1>())
i->doAction(), delete i; // "X1::doAction"
if (Widget* i = Widget::Construct<X2>(123))
i->doAction(), delete i; // "X2::doAction with 123"
if (Widget* i = Widget::Construct<X3>())
i->doAction(), delete i; // "X3::doAction with 12.5"
if (Widget* i = Widget::Construct<int>())
i->doAction(), delete i; // no-op
}
/*******************************************************************/
Rather than outputting three lines, only one is now output. The code compiled
correctly on clang 7 and earlier and also compiles correctly on gcc.
The fix seems to be relatively trivial, and doesn't break any test-cases:
Index: lib/AST/DeclBase.cpp
===================================================================
--- lib/AST/DeclBase.cpp (revision 350505)
+++ lib/AST/DeclBase.cpp (working copy)
@@ -1407,7 +1407,8 @@
// Skip friends and local extern declarations unless they're the first
// declaration of the entity.
- if ((D->isLocalExternDecl() || D->getFriendObjectKind()) &&
+ if ((D->isLocalExternDecl() ||
+ D->getFriendObjectKind() == Decl::FOK_Declared) &&
D != D->getCanonicalDecl())
return true;</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>