Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Friend declaration not picked up for function with auto-deduced return type #30825

Closed Quuxplusone closed 6 years ago

Quuxplusone commented 7 years ago
Bugzilla Link PR31852
Status RESOLVED FIXED
Importance P normal
Reported by Louis Dionne (ldionne.2@gmail.com)
Reported on 2017-02-02 21:29:08 -0800
Last modified on 2018-09-12 06:26:41 -0700
Version trunk
Hardware PC All
CC ardenisthebest@gmail.com, ashaduri@gmail.com, blitzrakete@gmail.com, dror@psybear.com, egor.pugin@gmail.com, henrik@mysko.org, malcolm.parsons@gmail.com, timshen91@gmail.com, tstellar@redhat.com, vittorio.romeo@outlook.com, zilla@kayari.org
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also

Hi,

The following code does not compile under Clang trunk

template class Template; template <typename T, typename ...X> class Specialized;

template <typename T, typename ...X> class Specialized<T, Template...> { template friend auto f(); static constexpr int member = 0; };

template auto f() { (void)Specialized::member; }

template auto f();

The error is

test.cpp:11:34: error: 'member' is a private member of 'Specialized' auto f() { (void)Specialized::member; } ^ test.cpp:13:15: note: in instantiation of function template specialization 'f' requested here template auto f(); ^ test.cpp:7:14: note: implicitly declared private here static int member; ^ 1 error generated.

Live example on Wandbox: http://melpon.org/wandbox/permlink/aEH7GireSTaP0n3x Note that GCC compiles this fine: http://melpon.org/wandbox/permlink/Zdckf85spwKr7yqa

Also note that using void instead of auto as the return type of f() fixes the problem: http://melpon.org/wandbox/permlink/TOH067rDrJIcweiC

Quuxplusone commented 7 years ago
Slightly simpler:

template<typename V> auto get(V&) { }

template<typename>
  class variant
  {
    template<typename V> friend auto get(V&);
  };

int main()
{
  variant<int> v{};
  get(v);
}

var.cc:12:3: error: call to 'get' is ambiguous
  get(v);
  ^~~
var.cc:1:27: note: candidate function [with V = variant<int>]
template<typename V> auto get(V&) { }
                          ^
var.cc:6:38: note: candidate function [with V = variant<int>]
    template<typename V> friend auto get(V&);
                                     ^
1 error generated.
Quuxplusone commented 7 years ago

This is affecting libstdc++ trunk as well.

Quuxplusone commented 6 years ago

Got bit by this again. This is probably a duplicate of: https://bugs.llvm.org/show_bug.cgi?id=33222

Minimal example to reproduce the "is a private member" error:

template <typename U>
auto foo(U u)
{
    u.v;
}

template <typename T>
class X
{
    T v;

public:
    template <typename U>
    friend auto foo(U);
};

int main()
{
    ::foo(X<int>{});
}
Quuxplusone commented 6 years ago
(In reply to Tim Shen from comment #2)
> This is affecting libstdc++ trunk <variant> as well.

I've added a workaround in https://gcc.gnu.org/r258854
Quuxplusone commented 6 years ago
(In reply to Jonathan Wakely from comment #4)
> (In reply to Tim Shen from comment #2)
> > This is affecting libstdc++ trunk <variant> as well.
>
> I've added a workaround in https://gcc.gnu.org/r258854

The calls to __get() in variant's operators are also causing ambiguity errors:

include/c++/7.3.0/variant:287:3: error: call to '__get' is ambiguous
  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Patch against trunk:

@@ -272,8 +272,8 @@
     constexpr bool \
     __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \
     { \
-      return __get<_Np>(std::forward<_Variant>(__lhs)) \
-     __OP __get<_Np>(std::forward<_Variant>(__rhs)); \
+      return __variant::__get<_Np>(std::forward<_Variant>(__lhs)) \
+     __OP __variant::__get<_Np>(std::forward<_Variant>(__rhs)); \
     }

   _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
Quuxplusone commented 6 years ago

Thanks, fixed on trunk by r259135

Quuxplusone commented 6 years ago

Thanks, this has been fixed in r341775.