// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s template <class T> class A { public: void f(T a) { }// expected-note 2{{must qualify identifier to find this declaration in dependent base class}} void g();// expected-note 2{{must qualify identifier to find this declaration in dependent base class}} }; template <class T> class B : public A<T> { public: void z(T a) { f(a); // expected-warning 2{{use of identifier 'f' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} g(); // expected-warning 2{{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} } }; template class B<int>; // expected-note {{requested here}} template class B<char>; // expected-note {{requested here}} void test() { B<int> b; b.z(3); } struct A2 { template<class T> void f(T) { XX; //expected-error {{use of undeclared identifier 'XX'}} A2::XX; //expected-error {{no member named 'XX' in 'A2'}} } }; template void A2::f(int); template<class T0> struct A3 { template<class T1> void f(T1) { XX; //expected-error {{use of undeclared identifier 'XX'}} } }; template void A3<int>::f(int); template<class T0> struct A4 { void f(char) { XX; //expected-error {{use of undeclared identifier 'XX'}} } }; template class A4<int>; namespace lookup_dependent_bases_id_expr { template<class T> class A { public: int var; }; template<class T> class B : public A<T> { public: void f() { var = 3; // expected-warning {{use of undeclared identifier 'var'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}} } }; template class B<int>; } namespace lookup_dependent_base_class_static_function { template <class T> class A { public: static void static_func();// expected-note {{must qualify identifier to find this declaration in dependent base class}} void func();// expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template <class T> class B : public A<T> { public: static void z2(){ static_func(); // expected-warning {{use of identifier 'static_func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} func(); // expected-warning {{use of identifier 'func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}} } }; template class B<int>; // expected-note {{requested here}} } namespace lookup_dependent_base_class_default_argument { template<class T> class A { public: static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template<class T> class B : public A<T> { public: void g1(int p = f1());// expected-warning {{use of identifier 'f1' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} void g2(int p = f2());// expected-warning {{use of identifier 'f2' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}} }; void foo() { B<int> b; b.g1(); // expected-note {{required here}} b.g2(); // expected-note {{required here}} } } namespace lookup_dependent_base_class_friend { template <class T> class B { public: static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template <class T> class A : public B<T> { public: friend void foo(A<T> p){ g(); // expected-warning {{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} } }; int main2() { A<int> a; foo(a); // expected-note {{requested here}} } } namespace lookup_dependent_base_no_typo_correction { class C { public: int m_hWnd; }; template <class T> class A : public T { public: void f(int hWnd) { m_hWnd = 1; // expected-warning {{use of undeclared identifier 'm_hWnd'; unqualified lookup into dependent bases of class template 'A' is a Microsoft extension}} } }; template class A<C>; } namespace PR12701 { class A {}; class B {}; template <class T> class Base { public: bool base_fun(void* p) { return false; } // expected-note {{must qualify identifier to find this declaration in dependent base class}} operator T*() const { return 0; } }; template <class T> class Container : public Base<T> { public: template <typename S> bool operator=(const Container<S>& rhs) { return base_fun(rhs); // expected-warning {{use of identifier 'base_fun' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} } }; void f() { Container<A> text_provider; Container<B> text_provider2; text_provider2 = text_provider; // expected-note {{in instantiation of function template specialization}} } } // namespace PR12701 namespace PR16014 { struct A { int a; static int sa; }; template <typename T> struct B : T { int foo() { return a; } // expected-warning {{lookup into dependent bases}} int *bar() { return &a; } // expected-warning {{lookup into dependent bases}} int baz() { return T::a; } int T::*qux() { return &T::a; } static int T::*stuff() { return &T::a; } static int stuff1() { return T::sa; } static int *stuff2() { return &T::sa; } static int stuff3() { return sa; } // expected-warning {{lookup into dependent bases}} static int *stuff4() { return &sa; } // expected-warning {{lookup into dependent bases}} }; template <typename T> struct C : T { int foo() { return b; } // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}} expected-warning {{lookup into dependent bases}} int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}} expected-warning {{lookup into dependent bases}} int baz() { return T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} int T::*qux() { return &T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} \ // expected-warning {{unqualified lookup into dependent bases of class template 'C'}} }; template struct B<A>; template struct C<A>; // expected-note-re 1+ {{in instantiation of member function 'PR16014::C<PR16014::A>::{{.*}}' requested here}} template <typename T> struct D : T { struct Inner { int foo() { // FIXME: MSVC can find this in D's base T! Even worse, if ::sa exists, // clang will use it instead. return sa; // expected-error {{use of undeclared identifier 'sa'}} } }; }; template struct D<A>; } namespace PR19233 { template <class T> struct A : T { void foo() { ::undef(); // expected-error {{no member named 'undef' in the global namespace}} } void bar() { ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}} } void baz() { B::qux(); // expected-error {{use of undeclared identifier 'B'}} \ // expected-warning {{unqualified lookup into dependent bases of class template 'A'}} } }; struct B { void qux(); }; struct C : B { }; template struct A<C>; // No error! B is a base of A<C>, and qux is available. struct D { }; template struct A<D>; // expected-note {{in instantiation of member function 'PR19233::A<PR19233::D>::baz' requested here}} } namespace nonmethod_missing_this { template <typename T> struct Base { int y = 42; }; template <typename T> struct Derived : Base<T> { int x = y; // expected-warning {{lookup into dependent bases}} auto foo(int j) -> decltype(y * j) { // expected-warning {{lookup into dependent bases}} return y * j; // expected-warning {{lookup into dependent bases}} } int bar() { return [&] { return y; }(); // expected-warning {{lookup into dependent bases}} } }; template struct Derived<int>; } namespace typedef_in_base { template <typename T> struct A { typedef T NameFromBase; }; template <typename T> struct B : A<T> { NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}} }; static_assert(sizeof(B<int>) == 4, ""); } namespace struct_in_base { template <typename T> struct A { struct NameFromBase {}; }; template <typename T> struct B : A<T> { NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}} }; static_assert(sizeof(B<int>) == 1, ""); } namespace enum_in_base { template <typename T> struct A { enum NameFromBase { X }; }; template <typename T> struct B : A<T> { NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}} }; static_assert(sizeof(B<int>) == sizeof(A<int>::NameFromBase), ""); } namespace two_types_in_base { template <typename T> struct A { typedef T NameFromBase; }; // expected-note {{member found by ambiguous name lookup}} template <typename T> struct B { struct NameFromBase { T m; }; }; // expected-note {{member found by ambiguous name lookup}} template <typename T> struct C : A<T>, B<T> { NameFromBase m; // expected-error {{member 'NameFromBase' found in multiple base classes of different types}} expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} }; static_assert(sizeof(C<int>) != 0, ""); // expected-note {{in instantiation of template class 'two_types_in_base::C<int>' requested here}} } namespace type_and_decl_in_base { template <typename T> struct A { typedef T NameFromBase; }; template <typename T> struct B { static const T NameFromBase = 42; }; template <typename T> struct C : A<T>, B<T> { NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}} }; } namespace classify_type_from_base { template <typename T> struct A { struct NameFromBase {}; }; template <typename T> struct B : A<T> { A<NameFromBase> m; // expected-warning {{found via unqualified lookup into dependent bases}} }; } namespace classify_nontype_from_base { // MSVC does not do lookup of non-type declarations from dependent template base // classes. The extra lookup only applies to types. template <typename T> struct A { void NameFromBase() {} }; template <void (*F)()> struct B { }; template <typename T> struct C : A<T> { B<C::NameFromBase> a; // correct B<NameFromBase> b; // expected-error {{use of undeclared identifier 'NameFromBase'}} }; } namespace template_in_base { template <typename T> struct A { template <typename U> struct NameFromBase { U x; }; }; template <typename T> struct B : A<T> { // Correct form. typename B::template NameFromBase<T> m; }; template <typename T> struct C : A<T> { // Incorrect form. NameFromBase<T> m; // expected-error {{unknown type name 'NameFromBase'}} //expected-error@-1 {{expected member name or ';' after declaration specifiers}} }; } namespace type_in_inner_class_in_base { template <typename T> struct A { struct B { typedef T NameFromBase; }; }; template <typename T> struct C : A<T>::B { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}} } namespace type_in_inner_template_class_in_base { template <typename T> struct A { template <typename U> struct B { typedef U InnerType; }; }; template <typename T> struct C : A<T>::template B<T> { NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}} }; } namespace have_nondependent_base { template <typename T> struct A { // Nothing, lookup should fail. }; template <typename T> struct B : A<T> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}} struct C : A<int> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}} } namespace type_in_base_of_dependent_base { struct A { typedef int NameFromBase; }; template <typename T> struct B : A {}; template <typename T> struct C : B<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} } namespace type_in_second_dependent_base { template <typename T> struct A {}; template<typename T> struct B { typedef T NameFromBase; }; template <typename T> struct D : A<T>, B<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} } namespace type_in_second_non_dependent_base { struct A {}; struct B { typedef int NameFromBase; }; template<typename T> struct C : A, B {}; template <typename T> struct D : C<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} } namespace type_in_virtual_base_of_dependent_base { template <typename T> struct A { typedef T NameFromBase; }; template <typename T> struct B : virtual A<T> {}; template <typename T> struct C : B<T>, virtual A<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} C<int> c; } namespace type_in_base_of_multiple_dependent_bases { template <typename T> struct A { typedef T NameFromBase; }; template <typename T> struct B : public A<T> {}; template <typename T> struct C : B<T>, public A<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-warning {{direct base 'A<int>' is inaccessible due to ambiguity:}} C<int> c; // expected-note {{in instantiation of template class 'type_in_base_of_multiple_dependent_bases::C<int>' requested here}} } namespace type_in_dependent_base_of_non_dependent_type { template<typename T> struct A { typedef int NameFromBase; }; template<typename T> struct B : A<T> { struct C; template<typename TT> struct D : C { NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} }; struct E : C { NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} }; }; template<typename T> struct B<T>::C : B { NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} }; template<typename T> struct F : B<T>::C { NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}} }; } namespace lookup_in_function_contexts { template <typename T> struct A { typedef T NameFromBase; }; template <typename T> struct B : A<T> { // expected-warning@+1 {{lookup into dependent bases}} static auto lateSpecifiedFunc() -> decltype(NameFromBase()) { return {}; } static void memberFunc() { NameFromBase x; // expected-warning {{lookup into dependent bases}} } static void funcLocalClass() { struct X { NameFromBase x; // expected-warning {{lookup into dependent bases}} } y; } void localClassMethod() { struct X { void bar() { NameFromBase m; // expected-warning {{lookup into dependent bases}} } } x; x.bar(); } static void funcLambda() { auto l = []() { NameFromBase x; // expected-warning {{lookup into dependent bases}} }; l(); } static constexpr int constexprFunc() { NameFromBase x = {}; // expected-warning {{lookup into dependent bases}} return sizeof(x); } static auto autoFunc() { NameFromBase x; // expected-warning {{lookup into dependent bases}} return x; } }; // Force us to parse the methods. template struct B<int>; } namespace function_template_deduction { // Overloaded function templates. template <int N> int f() { return N; } template <typename T> int f() { return sizeof(T); } // Dependent base class with type. template <typename T> struct A { typedef T NameFromBase; }; template <typename T> struct B : A<T> { // expected-warning@+1 {{found via unqualified lookup into dependent bases}} int x = f<NameFromBase>(); }; // Dependent base class with enum. template <typename T> struct C { enum { NameFromBase = 4 }; }; template <typename T> struct D : C<T> { // expected-warning@+1 {{use of undeclared identifier 'NameFromBase'; unqualified lookup into dependent bases}} int x = f<NameFromBase>(); }; } namespace function_template_undef_impl { template<class T> void f() { Undef::staticMethod(); // expected-error {{use of undeclared identifier 'Undef'}} UndefVar.method(); // expected-error {{use of undeclared identifier 'UndefVar'}} } } namespace PR20716 { template <template <typename T> class A> struct B : A<int> { XXX x; // expected-error {{unknown type name}} }; template <typename T> struct C {}; template <typename T> using D = C<T>; template <typename T> struct E : D<T> { XXX x; // expected-error {{unknown type name}} }; } namespace PR23810 { void f(int); struct Base { void f(); // expected-note{{must qualify identifier to find this declaration in dependent base class}} }; template <typename T> struct Template : T { void member() { f(); // expected-warning {{found via unqualified lookup into dependent bases}} } }; void test() { Template<Base> x; x.member(); // expected-note{{requested here}} }; } namespace PR23823 { // Don't delay lookup in SFINAE context. template <typename T> decltype(g(T())) check(); // expected-note{{candidate template ignored: substitution failure [with T = int]: use of undeclared identifier 'g'}} decltype(check<int>()) x; // expected-error{{no matching function for call to 'check'}} void h(); template <typename T> decltype(h(T())) check2(); // expected-note{{candidate template ignored: substitution failure [with T = int]: no matching function for call to 'h'}} decltype(check2<int>()) y; // expected-error{{no matching function for call to 'check2'}} } // We also allow unqualified lookup into bases in contexts where the we know the // undeclared identifier *must* be a type, such as a new expression or catch // parameter type. template <typename T> struct UseUnqualifiedTypeNames : T { void foo() { void *P = new TheType; // expected-warning {{unqualified lookup}} expected-error {{no type}} size_t x = __builtin_offsetof(TheType, f2); // expected-warning {{unqualified lookup}} expected-error {{no type}} try { } catch (TheType) { // expected-warning {{unqualified lookup}} expected-error {{no type}} } enum E : IntegerType { E0 = 42 }; // expected-warning {{unqualified lookup}} expected-error {{no type}} _Atomic(TheType) a; // expected-warning {{unqualified lookup}} expected-error {{no type}} } void out_of_line(); }; template <typename T> void UseUnqualifiedTypeNames<T>::out_of_line() { void *p = new TheType; // expected-warning {{unqualified lookup}} expected-error {{no type}} } struct Base { typedef int IntegerType; struct TheType { int f1, f2; }; }; template struct UseUnqualifiedTypeNames<Base>; struct BadBase { }; template struct UseUnqualifiedTypeNames<BadBase>; // expected-note-re 2 {{in instantiation {{.*}} requested here}} namespace partial_template_lookup { class Bar; class Spare; template <class T, class X = Bar> class FooTemplated; class FooBase { public: typedef int BaseTypedef; }; // Partial template spec (unused) template <class T> class FooTemplated<T, Spare> {}; // Partial template spec (used) template <class T> class FooTemplated<T, Bar> : public FooBase {}; // Full template spec template <class T, class X> class FooTemplated : public FooTemplated<T, Bar> { public: BaseTypedef Member; // expected-warning {{unqualified lookup}} }; }