Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Clang fails to compile (possibly) legal code #25265

Open Quuxplusone opened 8 years ago

Quuxplusone commented 8 years ago
Bugzilla Link PR25266
Status NEW
Importance P normal
Reported by Hyman Rosen (hyrosen@mail.com)
Reported on 2015-10-20 14:18:33 -0700
Last modified on 2015-10-21 02:18:18 -0700
Version 3.7
Hardware PC Linux
CC dgregor@apple.com, hyrosen@mail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
Here's a bit of code which clang 3.7 doesn't compile:

template <class T> struct R { static T& r(); };
struct M {
    static char m(M&);
    template <class T>
    static int m(const T&);
};
template <class T> struct A;
template <class T>
struct B {
    struct U { };
    struct V { M& operator, (U) const; };
    enum { v = sizeof(M::m((R<V>::r(), R<A<T>*>::r()))) };
};
template <class T> struct A { B<T> y; };
int main()
{
//  A<int>();  // Works if uncommented.
    B<int>();
}

Clang reports
h.cpp:14:36: error: field has incomplete type 'B<int>'
template <class T> struct A { B<T> y; };
                                   ^
h.cpp:12:38: note: in instantiation of template class 'A<int>' requested here
    enum { v = sizeof(M::m((R<V>::r(), R<A<T>*>::r()))) };
                                     ^
h.cpp:18:5: note: in instantiation of template class 'B<int>' requested here
    B<int>();
    ^
h.cpp:9:8: note: definition of 'B<int>' is not complete until the closing '}'
struct B {
       ^
1 error generated.

If I uncomment the marked line, clang compiles the code.  I don't know why the
compiler wants A<T> to be complete when it's just dealing with A<T>*, or why
uncommenting the marked line helps.
Quuxplusone commented 8 years ago
(In reply to comment #0)
> I don't know why the compiler wants A<T> to be complete when
> it's just dealing with A<T>*

Argument-dependent lookup for operator, needs to look for friend functions
defined within A<T>, because it's an associated class of the lookup.

> or why uncommenting the marked line helps.

When ADL triggers an instantiation, if that instantiation can't be performed
because we're already in the middle of doing it, we silently ignore the attempt
to complete the type. That's probably a bug; we should probably reject this
irrespective of whether A<int> or B<int> is instantiated first.