llvm/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp

// RUN: %clang_cc1 -Wno-unused-value -verify %s

namespace N0 {
  struct A {
    int x0;
    static int y0;
    int x1;
    static int y1;

    void f0();
    static void g0();
    void f1();
    static void g1();

    using M0 = int;
    using M1 = int;

    struct C0 { };
    struct C1 { };
  };

  template<typename T>
  struct B : A {
    int x2;
    static int y2;

    void f2();
    static void g2();

    using M2 = int;

    struct C2 { };

    using A::x1;
    using A::y1;
    using A::f1;
    using A::g1;
    using A::M1;
    using A::C1;

    using T::x3;
    using T::y3;
    using T::f3;
    using T::g3;
    using typename T::M3;
    using typename T::C3;

    void not_instantiated(B *a, B &b) {
      // All of the following should be found in the current instantiation.

      new M0;
      new B::M0;
      new A::M0;
      new B::A::M0;
      new C0;
      new B::C0;
      new A::C0;
      new B::A::C0;
      new M1;
      new B::M1;
      new A::M1;
      new B::A::M1;
      new C1;
      new B::C1;
      new A::C1;
      new B::A::C1;
      new M2;
      new B::M2;
      new C2;
      new B::C2;
      new M3;
      new B::M3;
      new C3;
      new B::C3;

      x0;
      B::x0;
      A::x0;
      B::A::x0;
      y0;
      B::y0;
      A::y0;
      B::A::y0;
      x1;
      B::x1;
      A::x1;
      B::A::x1;
      y1;
      B::y1;
      A::y1;
      B::A::y1;
      x2;
      B::x2;
      y2;
      B::y2;
      x3;
      B::x3;
      y3;
      B::y3;

      f0();
      B::f0();
      A::f0();
      B::A::f0();
      g0();
      B::g0();
      A::g0();
      B::A::g0();
      f1();
      B::f1();
      A::f1();
      B::A::f1();
      g1();
      B::g1();
      A::g1();
      B::A::g1();
      f2();
      B::f2();
      g2();
      B::g2();
      f3();
      B::f3();
      g3();
      B::g3();

      this->x0;
      this->B::x0;
      this->A::x0;
      this->B::A::x0;
      this->y0;
      this->B::y0;
      this->A::y0;
      this->B::A::y0;
      this->x1;
      this->B::x1;
      this->A::x1;
      this->B::A::x1;
      this->y1;
      this->B::y1;
      this->A::y1;
      this->B::A::y1;
      this->x2;
      this->B::x2;
      this->y2;
      this->B::y2;
      this->x3;
      this->B::x3;
      this->y3;
      this->B::y3;

      this->f0();
      this->B::f0();
      this->A::f0();
      this->B::A::f0();
      this->g0();
      this->B::g0();
      this->A::g0();
      this->B::A::g0();
      this->f1();
      this->B::f1();
      this->A::f1();
      this->B::A::f1();
      this->g1();
      this->B::g1();
      this->A::g1();
      this->B::A::g1();
      this->f2();
      this->B::f2();
      this->g2();
      this->B::g2();
      this->f3();
      this->B::f3();
      this->g3();
      this->B::g3();

      a->x0;
      a->B::x0;
      a->A::x0;
      a->B::A::x0;
      a->y0;
      a->B::y0;
      a->A::y0;
      a->B::A::y0;
      a->x1;
      a->B::x1;
      a->A::x1;
      a->B::A::x1;
      a->y1;
      a->B::y1;
      a->A::y1;
      a->B::A::y1;
      a->x2;
      a->B::x2;
      a->y2;
      a->B::y2;
      a->x3;
      a->B::x3;
      a->y3;
      a->B::y3;

      a->f0();
      a->B::f0();
      a->A::f0();
      a->B::A::f0();
      a->g0();
      a->B::g0();
      a->A::g0();
      a->B::A::g0();
      a->f1();
      a->B::f1();
      a->A::f1();
      a->B::A::f1();
      a->g1();
      a->B::g1();
      a->A::g1();
      a->B::A::g1();
      a->f2();
      a->B::f2();
      a->g2();
      a->B::g2();
      a->f3();
      a->B::f3();
      a->g3();
      a->B::g3();

      (*this).x0;
      (*this).B::x0;
      (*this).A::x0;
      (*this).B::A::x0;
      (*this).y0;
      (*this).B::y0;
      (*this).A::y0;
      (*this).B::A::y0;
      (*this).x1;
      (*this).B::x1;
      (*this).A::x1;
      (*this).B::A::x1;
      (*this).y1;
      (*this).B::y1;
      (*this).A::y1;
      (*this).B::A::y1;
      (*this).x2;
      (*this).B::x2;
      (*this).y2;
      (*this).B::y2;
      (*this).x3;
      (*this).B::x3;
      (*this).y3;
      (*this).B::y3;

      (*this).f0();
      (*this).B::f0();
      (*this).A::f0();
      (*this).B::A::f0();
      (*this).g0();
      (*this).B::g0();
      (*this).A::g0();
      (*this).B::A::g0();
      (*this).f1();
      (*this).B::f1();
      (*this).A::f1();
      (*this).B::A::f1();
      (*this).g1();
      (*this).B::g1();
      (*this).A::g1();
      (*this).B::A::g1();
      (*this).f2();
      (*this).B::f2();
      (*this).g2();
      (*this).B::g2();
      (*this).f3();
      (*this).B::f3();
      (*this).g3();
      (*this).B::g3();

      b.x0;
      b.B::x0;
      b.A::x0;
      b.B::A::x0;
      b.y0;
      b.B::y0;
      b.A::y0;
      b.B::A::y0;
      b.x1;
      b.B::x1;
      b.A::x1;
      b.B::A::x1;
      b.y1;
      b.B::y1;
      b.A::y1;
      b.B::A::y1;
      b.x2;
      b.B::x2;
      b.y2;
      b.B::y2;
      b.x3;
      b.B::x3;
      b.y3;
      b.B::y3;

      b.f0();
      b.B::f0();
      b.A::f0();
      b.B::A::f0();
      b.g0();
      b.B::g0();
      b.A::g0();
      b.B::A::g0();
      b.f1();
      b.B::f1();
      b.A::f1();
      b.B::A::f1();
      b.g1();
      b.B::g1();
      b.A::g1();
      b.B::A::g1();
      b.f2();
      b.B::f2();
      b.g2();
      b.B::g2();
      b.f3();
      b.B::f3();
      b.g3();
      b.B::g3();

      // None of the following should be found in the current instantiation.

      new M4; // expected-error{{unknown type name 'M4'}}
      new B::M4; // expected-error{{no type named 'M4' in 'B<T>'}}
      new A::M4; // expected-error{{no type named 'M4' in 'N0::A'}}
      new B::A::M4; // expected-error{{no type named 'M4' in 'N0::A'}}

      x4; // expected-error{{use of undeclared identifier 'x4'}}
      B::x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      f4(); // expected-error{{use of undeclared identifier 'f4'}}
      B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}
      B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}

      this->x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      this->B::x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      this->A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      this->B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      this->f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      this->B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      this->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}
      this->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}

      a->x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      a->B::x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      a->A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      a->B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      a->f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      a->B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      a->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}
      a->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}

      (*this).x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      (*this).B::x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      (*this).A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      (*this).B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      (*this).f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      (*this).B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      (*this).A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}
      (*this).B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}

      b.x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      b.B::x4; // expected-error{{no member named 'x4' in 'B<T>'}}
      b.A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      b.B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}}
      b.f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      b.B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}}
      b.A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}
      b.B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}}
    }
  };
} // namespace N0

namespace N1 {
  struct A {
    template<int I>
    void f();
  };

  template<typename T>
  struct B {
    template<int I>
    void f();

    A x;
    A g();

    void not_instantiated(B *a, B &b) {
      f<0>();
      this->f<0>();
      a->f<0>();
      (*this).f<0>();
      b.f<0>();

      x.f<0>();
      this->x.f<0>();
      a->x.f<0>();
      (*this).x.f<0>();
      b.x.f<0>();

      // FIXME: None of these should require 'template'!
      g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}}
      this->g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}}
      a->g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}}
      (*this).g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}}
      b.g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}}
    }
  };
} // namespace N1

namespace N2 {
  template<typename T>
  struct A {
    struct B {
      using C = A;

      void not_instantiated(A *a, B *b) {
        b->x; // expected-error{{no member named 'x' in 'N2::A::B'}}
        b->B::x; // expected-error{{no member named 'x' in 'N2::A::B'}}
        a->B::C::x; // expected-error{{no member named 'x' in 'A<T>'}}
      }
    };

    void not_instantiated(A *a, B *b) {
      b->x;
      b->B::x;
      a->B::C::x;
    }
  };
} // namespace N2

namespace N3 {
  struct A { };

  template<typename T>
  struct B : A {
    void not_instantiated() {
      // Dependent, lookup context is the current instantiation.
      this->operator=(*this);
      // Not dependent, the lookup context is A (not the current instantiation).
      this->A::operator=(*this);
    }
  };

  template<typename T>
  struct C {
    template<typename U>
    void operator=(int);

    void not_instantiated() {
      operator=<int>(0);
      C::operator=<int>(0);
      this->operator=<int>(0);
      this->C::operator=<int>(0);

      operator=(*this);
      C::operator=(*this);
      this->operator=(*this);
      this->C::operator=(*this);
    }
  };

  template<typename T>
  struct D {
    auto not_instantiated() -> decltype(operator=(0)); // expected-error {{use of undeclared 'operator='}}
  };

  template<typename T>
  struct E {
    auto instantiated(E& e) -> decltype(operator=(e)); // expected-error {{use of undeclared 'operator='}}
  };

  template struct E<int>; // expected-note {{in instantiation of template class 'N3::E<int>' requested here}}
} // namespace N3

namespace N4 {
  template<typename T>
  struct A {
    void not_instantiated(A a, A<T> b, T c) {
      a->x;
      b->x;
      c->x;
    }

    void instantiated(A a, A<T> b, T c) {
      a->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
            // expected-error@-1 {{no member named 'x' in 'N4::A<int>'}}
      b->x; // expected-error {{member reference type 'A<int>' is not a pointer; did you mean to use '.'?}}
            // expected-error@-1 {{no member named 'x' in 'N4::A<int>'}}
      c->x; // expected-error {{member reference type 'int' is not a pointer}}
    }
  };

  template void A<int>::instantiated(A<int>, A<int>, int); // expected-note {{in instantiation of}}

  struct B {
    int x;

    void f();
  };

  template<typename T>
  struct C {
    B *operator->();

    void not_instantiated(C a, C<T> b, T c) {
      a->x;
      b->x;
      c->x;
    }

    void instantiated(C a, C<T> b, T c) {
      a->x;
      b->x;
      c->x; // expected-error {{member reference type 'int' is not a pointer}}
    }
  };

  template void C<int>::instantiated(C, C, int); // expected-note {{in instantiation of}}

  template<typename T>
  struct D {
    T *operator->();

    void not_instantiated(D a) {
      a->x;
      a->y;
      a->f();
      a->g();

      a->T::x;
      a->T::y;
      a->T::f();
      a->T::g();

      // FIXME: 'U' should be a dependent name, and its lookup context should be 'a.operator->()'!
      a->U::x; // expected-error {{use of undeclared identifier 'U'}}
      a->U::y; // expected-error {{use of undeclared identifier 'U'}}
      a->U::f(); // expected-error {{use of undeclared identifier 'U'}}
      a->U::g(); // expected-error {{use of undeclared identifier 'U'}}
    }

    void instantiated(D a) {
      a->x;
      a->y; // expected-error {{no member named 'y' in 'N4::B'}}
      a->f();
      a->g(); // expected-error {{no member named 'g' in 'N4::B'}}

      a->T::x;
      a->T::y; // expected-error {{no member named 'y' in 'N4::B'}}
      a->T::f();
      a->T::g(); // expected-error {{no member named 'g' in 'N4::B'}}
    }
  };

  template void D<B>::instantiated(D); // expected-note {{in instantiation of}}

  template<typename T>
  struct Typo {
    T *operator->();

    void not_instantiated(Typo a) {
      a->Not_instantiated;
      a->typo;
      a->T::Not_instantiated;
      a->T::typo;
    }
  };
} // namespace N4

namespace N5 {
  struct A {
    int x;
  };

  template<typename T>
  void f() {
    A y = T::x; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
    y.x;
  }

  template void f<int>(); // expected-note {{in instantiation of}}

  struct B {
    template<typename T>
    B(T&&);

    int x;
  };

  template<typename T>
  void g(T y) {
    B z([&]() { // expected-note {{while substituting into a lambda expression here}}
      h(&y); // expected-error {{use of undeclared identifier 'h'}}
    });
    z.x;
  }

  template void g(int); // expected-note {{in instantiation of}}
} // namespace N5