[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