forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			634 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			634 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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 {{no template named 'NameFromBase'}}
 | |
| };
 | |
| }
 | |
| 
 | |
| 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}}
 | |
| };
 | |
| }
 |