[LLVMdev] Clang bug?

Adam Peterson alpha.eta.pi at gmail.com
Fri Sep 28 17:11:21 PDT 2012


This doesn't appear to me to be the same issue (but of course I don't
know clang as well as you all do).  This code appears invalid (and G++
rejects it with a similar "no type named ..." error message), whereas
the original code is valid C++ (both C++98 and C++11).

On Fri, Sep 28, 2012 at 3: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
>
> On Fri, Sep 28, 2012 at 7:51 AM, Howard Hinnant <hhinnant at apple.com> wrote:
>>
>> That is one evil bug!
>>
>> I just tested it against tip-of-trunk clang and it appears to be fixed
>> there (just fyi for everyone).
>>
>> Howard
>>
>> On Sep 27, 2012, at 7:17 PM, Adam Peterson <alpha.eta.pi at gmail.com> wrote:
>>
>> > Is this a relevant location to provide information about what I
>> > believe is a compiler bug in clang?  If not, please forgive me for
>> > posting it here.  (Perhaps you can redirect me to some place more
>> > appropriate.)  If so, here are the details:
>> >
>> > I have a short 15-line C++ program using only one standard header that
>> > clang fails to compile properly under C++11 with the new standard
>> > library (although the code itself doesn't use any C++11-specific
>> > syntax), but G++ (4.6-Ubuntu and 4.2-Darwin) compiles it fine:
>> >
>> >    #include <map>
>> >    using std::map;
>> >
>> >    template<typename K>
>> >    struct Templ8 {
>> >        struct Member {
>> >            typename map<K,Member*>::iterator it;
>> >        };
>> >        typedef typename map<K,Member*>::iterator iterator_type;
>> >    };
>> >
>> >    int main() {
>> >        Templ8<int> test;
>> >    }
>> >
>> >
>> >
>> > This is the command-line:
>> >    clang++ -stdlib=libc++ -std=c++11 main_bug.cpp
>> > If either of the flags are removed (to compile in C++03 mode, or to
>> > use the non-clang standard library), the code compiles.  If the
>> > typedef is removed or commented out, clang++ compiles the code fine.
>> > If the typedef is moved inside the "Member" inner class, the code
>> > compiles fine (even if a second typedef pulls the symbol back into the
>> > main template scope).
>> >
>> > My clang version information:
>> >    Apple clang version 4.1 (tags/Apple/clang-421.11.65) (based on LLVM
>> > 3.1svn)
>> >    Target: x86_64-apple-darwin12.2.0
>> >    Thread model: posix
>> >
>> > The error output:
>> >
>> > main_bug.cpp:7:34: error: no type named 'iterator' in
>> > 'std::__1::map<int, Templ8<int>::Member *, std::__1::less<int>,
>> > std::__1::allocator<std::__1::pair<const int, Templ8<int>::Member
>> > *>>>'
>> >        typename map<K,Member*>::iterator it;
>> >        ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
>> > /usr/bin/../lib/c++/v1/type_traits:1184:57: note: in instantiation of
>> > member class 'Templ8<int>::Member' requested here
>> > decltype((_VSTD::declval<_Tp>() = _VSTD::declval<_Arg>(), true_type()))
>> >                                                        ^
>> > /usr/bin/../lib/c++/v1/type_traits:1186:1: note: while substituting
>> > deduced template arguments into function template
>> > '__is_assignable_test' [with _Tp = Templ8<int>::Member *&, _Arg = <no
>> > value>]
>> > __is_assignable_test(_Tp&&, _Arg&&);
>> > ^
>> > /usr/bin/../lib/c++/v1/type_traits:1214:14: note: in instantiation of
>> > template class 'std::__1::__is_assignable_imp<Templ8<int>::Member *&,
>> > Templ8<int>::Member *&, false>' requested here
>> >    : public __is_assignable_imp<_Tp, _Arg> {};
>> >             ^
>> > /usr/bin/../lib/c++/v1/type_traits:2616:38: note: in instantiation of
>> > template class 'std::__1::is_assignable<Templ8<int>::Member *&,
>> > Templ8<int>::Member *&>' requested here
>> >    : public __is_nothrow_assignable<is_assignable<_Tp, _Arg>::value,
>> > _Tp, _Arg>
>> >                                     ^
>> > /usr/bin/../lib/c++/v1/type_traits:2667:14: note: in instantiation of
>> > template class 'std::__1::is_nothrow_assignable<Templ8<int>::Member
>> > *&, Templ8<int>::Member *&>' requested here
>> >    : public is_nothrow_assignable<typename
>> > add_lvalue_reference<_Tp>::type,
>> >             ^
>> > /usr/bin/../lib/c++/v1/utility:250:20: note: (skipping 9 contexts in
>> > backtrace; use -ftemplate-backtrace-limit=0 to see all)
>> >                   is_nothrow_copy_assignable<second_type>::value)
>> >                   ^
>> > /usr/bin/../lib/c++/v1/__config:253:34: note: expanded from macro
>> > '_NOEXCEPT_'
>> > #  define _NOEXCEPT_(x) noexcept(x)
>> >                                 ^
>> > /usr/bin/../lib/c++/v1/memory:2386:15: note: in instantiation of
>> > template class
>> > 'std::__1::__libcpp_compressed_pair_imp<std::__1::__tree_end_node<std::__1::__tree_node_base<void
>> > *> *>,
>> >      std::__1::allocator<std::__1::__tree_node<std::__1::pair<int,
>> > Templ8<int>::Member *>, void *>>, 2>' requested here
>> >    : private __libcpp_compressed_pair_imp<_T1, _T2>
>> >              ^
>> > /usr/bin/../lib/c++/v1/__tree:813:56: note: in instantiation of
>> > template class
>> > 'std::__1::__compressed_pair<std::__1::__tree_end_node<std::__1::__tree_node_base<void
>> > *> *>,
>> >      std::__1::allocator<std::__1::__tree_node<std::__1::pair<int,
>> > Templ8<int>::Member *>, void *>>>' requested here
>> >    __compressed_pair<__end_node_t, __node_allocator>  __pair1_;
>> >                                                       ^
>> > /usr/bin/../lib/c++/v1/map:711:22: note: in instantiation of template
>> > class 'std::__1::__tree<std::__1::pair<int, Templ8<int>::Member *>,
>> > std::__1::__map_value_compare<int, Templ8<int>::Member *,
>> >      std::__1::less<int>, true>,
>> > std::__1::allocator<std::__1::pair<int, Templ8<int>::Member *>>>'
>> > requested here
>> >    typedef typename __base::__node_traits                 __node_traits;
>> >                     ^
>> > main_bug.cpp:9:22: note: in instantiation of template class
>> > 'std::__1::map<int, Templ8<int>::Member *, std::__1::less<int>,
>> > std::__1::allocator<std::__1::pair<const int, Templ8<int>::Member
>> > *>>>'
>> >      requested here
>> >    typedef typename map<K,Member*>::iterator iterator_type;
>> >                     ^
>> > main_bug.cpp:13:17: note: in instantiation of template class
>> > 'Templ8<int>' requested here
>> >    Templ8<int> test;
>> >                ^
>> > 1 error generated.
>> > _______________________________________________
>> > LLVM Developers mailing list
>> > LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>



More information about the llvm-dev mailing list