[LLVMdev] Clang bug?
Richard Smith
richard at metafoo.co.uk
Fri Sep 28 19:18:20 PDT 2012
On Fri, Sep 28, 2012 at 6:45 PM, Howard Hinnant <hhinnant at apple.com> wrote:
> On Sep 28, 2012, at 5:54 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>
> > Reduced testcase:
> >
> > template<typename T> struct A { typedef decltype(T() + 0) type; };
> > template<typename T> struct B {
> > struct C { typedef typename A<C*>::type type; };
> > typedef typename A<C*>::type type;
> > };
> > B<int> b;
> >
> > ... produces ...
> >
> > <stdin>:3:38: error: no type named 'type' in 'A<B<int>::C *>'
> > struct C { typedef typename A<C*>::type type; };
> > ~~~~~~~~~~~~~~~~^~~~
> > <stdin>:1:54: note: in instantiation of member class 'B<int>::C'
> requested here
> > template<typename T> struct A { typedef decltype(T() + 0) type; };
> > ^
> > <stdin>:4:20: note: in instantiation of template class 'A<B<int>::C *>'
> requested here
> > typedef typename A<C*>::type type;
> > ^
> > <stdin>:6:8: note: in instantiation of template class 'B<int>' requested
> here
> > B<int> b;
> > ^
> >
> > I think it would be worth filing this as a diagnostic QoR issue. We
> should be able to say something like
> >
> > <stdin>:3:38: error: member 'type' of 'A<B<int>::C *>' required
> recursively within the instantiation of 'A<B<int>::C *>', but it has not
> been instantiated yet
>
> Hi Richard,
>
> Is your position that tot clang/libc++ is in error for not producing a
> diagnostic?
>
No, my position is the opposite. Trunk clang + libc++ still reject this:
#include <type_traits>
template<typename T> struct S { static_assert(sizeof(T) == 1, ""); };
bool b = std::is_assignable<S<int>*&, S<int>*>::value;
... because is_assignable triggers the instantiation of S<int>.
I believe Clang is behaving correctly here. I don't know whether libc++'s
implementation is valid (I don't know under what circumstances the library
can use constructs which could depend on the completeness of user-provided
types) but I suspect it is not, and even if it were, we'd want to allow
this as a QoI issue. Here's a fix (first change: avoid overloaded
'operator,', second change: avoid ADL for __is_assignable_test):
--- type_traits (revision 164877)
+++ type_traits (working copy)
@@ -1187,10 +1187,15 @@
#endif // _LIBCPP_HAS_NO_VARIADICS
+template <class _Fst, class _Snd>
+struct __select_2nd {
+ typedef _Snd type;
+};
+
// is_assignable
template <class _Tp, class _Arg>
-decltype((_VSTD::declval<_Tp>() = _VSTD::declval<_Arg>(), true_type()))
+typename __select_2nd<decltype(_VSTD::declval<_Tp>() =
_VSTD::declval<_Arg>()), true_type>::type
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
__is_assignable_test(_Tp&&, _Arg&&);
#else
@@ -1209,7 +1214,7 @@
struct __is_assignable_imp
: public common_type
<
- decltype(__is_assignable_test(declval<_Tp>(), declval<_Arg>()))
+ decltype(_VSTD::__is_assignable_test(declval<_Tp>(),
declval<_Arg>()))
>::type {};
template <class _Tp, class _Arg>
I don't know whether there are other similar cases elsewhere in libc++, but
that's enough to get my is_assignable test to work.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120928/49b92df2/attachment.html>
More information about the llvm-dev
mailing list