<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>