[llvm-bugs] [Bug 38883] instantiating a friend member specialization declaration does not look up member specialization properly
via llvm-bugs
llvm-bugs at lists.llvm.org
Fri May 10 10:19:00 PDT 2019
https://bugs.llvm.org/show_bug.cgi?id=38883
Andy Gibbs <andyg1001 at hotmail.co.uk> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|FIXED |---
Version|5.0 |8.0
Hardware|PC |All
CC| |andyg1001 at hotmail.co.uk
Status|RESOLVED |REOPENED
--- Comment #2 from Andy Gibbs <andyg1001 at hotmail.co.uk> ---
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;
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190510/07fbc014/attachment.html>
More information about the llvm-bugs
mailing list