2016-05-25 05:23:54 +08:00
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
2011-09-07 08:14:57 +08:00
template < class T >
class A {
public :
2015-10-06 04:05:21 +08:00
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}}
2011-09-07 08:14:57 +08:00
} ;
template < class T >
class B : public A < T > {
public :
void z ( T a )
{
2015-10-06 04:05:21 +08:00
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}}
2011-09-07 08:14:57 +08:00
}
} ;
template class B < int > ; // expected-note {{requested here}}
2015-10-06 04:05:21 +08:00
template class B < char > ; // expected-note {{requested here}}
2011-09-07 08:14:57 +08:00
void test ( )
{
B < int > b ;
b . z ( 3 ) ;
}
2013-04-29 16:45:27 +08:00
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 > ;
2011-11-11 08:12:11 +08:00
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 ( ) {
2014-06-11 08:01:28 +08:00
var = 3 ; // expected-warning {{use of undeclared identifier 'var'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}}
2011-11-11 08:12:11 +08:00
}
} ;
template class B < int > ;
}
2011-09-07 08:14:57 +08:00
2011-11-16 07:33:34 +08:00
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}}
2011-11-17 11:44:24 +08:00
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}}
2011-11-16 07:33:34 +08:00
}
} ;
template class B < int > ; // expected-note {{requested here}}
}
2011-11-17 11:44:24 +08:00
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}}
}
2011-11-25 09:10:54 +08:00
}
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}}
}
}
2011-12-03 23:55:29 +08:00
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 ) {
2014-06-11 08:01:28 +08:00
m_hWnd = 1 ; // expected-warning {{use of undeclared identifier 'm_hWnd'; unqualified lookup into dependent bases of class template 'A' is a Microsoft extension}}
2011-12-03 23:55:29 +08:00
}
} ;
template class A < C > ;
}
2012-06-21 04:21:42 +08:00
namespace PR12701 {
class A { } ;
class B { } ;
template < class T >
class Base {
public :
2013-12-06 00:25:25 +08:00
bool base_fun ( void * p ) { return false ; } // expected-note {{must qualify identifier to find this declaration in dependent base class}}
2012-06-21 04:21:42 +08:00
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
2013-10-16 02:38:02 +08:00
namespace PR16014 {
struct A {
int a ;
static int sa ;
} ;
template < typename T > struct B : T {
2014-06-11 08:01:28 +08:00
int foo ( ) { return a ; } // expected-warning {{lookup into dependent bases}}
int * bar ( ) { return & a ; } // expected-warning {{lookup into dependent bases}}
2013-10-16 02:38:02 +08:00
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 ; }
2014-06-11 08:01:28 +08:00
static int stuff3 ( ) { return sa ; } // expected-warning {{lookup into dependent bases}}
static int * stuff4 ( ) { return & sa ; } // expected-warning {{lookup into dependent bases}}
2013-10-16 02:38:02 +08:00
} ;
template < typename T > struct C : T {
2014-06-11 08:01:28 +08:00
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}}
2013-10-16 02:38:02 +08:00
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'}}
2014-08-15 07:34:52 +08:00
int T : : * fuz ( ) { return & U : : a ; } / / expected - error { { use of undeclared identifier ' U ' } } \
// expected-warning {{unqualified lookup into dependent bases of class template 'C'}}
2013-10-16 02:38:02 +08:00
} ;
template struct B < A > ;
2013-12-14 09:07:05 +08:00
template struct C < A > ; // expected-note-re 1+ {{in instantiation of member function 'PR16014::C<PR16014::A>::{{.*}}' requested here}}
2013-10-16 02:38:02 +08:00
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 > ;
}
2014-03-26 04:31:28 +08:00
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 ( ) {
2014-08-15 07:34:52 +08:00
B : : qux ( ) ; / / expected - error { { use of undeclared identifier ' B ' } } \
// expected-warning {{unqualified lookup into dependent bases of class template 'A'}}
2014-03-26 04:31:28 +08:00
}
} ;
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}}
}
2014-06-11 08:01:28 +08:00
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 > ;
}
2014-07-09 04:05:48 +08:00
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 {
2015-02-19 12:28:23 +08:00
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}}
2014-07-09 04:05:48 +08:00
template < typename T > struct C : A < T > , B < T > {
2015-02-19 12:28:23 +08:00
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}}
2014-07-09 04:05:48 +08:00
} ;
2015-12-19 06:19:11 +08:00
static_assert ( sizeof ( C < int > ) ! = 0 , " " ) ; // expected-note {{in instantiation of template class 'two_types_in_base::C<int>' requested here}}
2014-07-09 04:05:48 +08:00
}
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'}}
}
2014-07-09 05:35:03 +08:00
namespace type_in_base_of_dependent_base {
struct A { typedef int NameFromBase ; } ;
template < typename T >
struct B : A { } ;
template < typename T >
2015-02-19 12:28:23 +08:00
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'}}
} ;
2014-07-09 05:35:03 +08:00
}
2014-07-09 04:05:48 +08:00
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 ( ) {
2014-07-09 05:35:03 +08:00
NameFromBase x ; // expected-warning {{lookup into dependent bases}}
2014-07-09 04:05:48 +08:00
}
static void funcLocalClass ( ) {
struct X {
2014-07-09 05:35:03 +08:00
NameFromBase x ; // expected-warning {{lookup into dependent bases}}
2014-07-09 04:05:48 +08:00
} y ;
}
void localClassMethod ( ) {
struct X {
void bar ( ) {
2014-07-09 05:35:03 +08:00
NameFromBase m ; // expected-warning {{lookup into dependent bases}}
2014-07-09 04:05:48 +08:00
}
} x ;
x . bar ( ) ;
}
static void funcLambda ( ) {
auto l = [ ] ( ) {
2014-07-09 05:35:03 +08:00
NameFromBase x ; // expected-warning {{lookup into dependent bases}}
2014-07-09 04:05:48 +08:00
} ;
l ( ) ;
}
static constexpr int constexprFunc ( ) {
2014-07-09 05:35:03 +08:00
NameFromBase x = { } ; // expected-warning {{lookup into dependent bases}}
2014-07-09 04:05:48 +08:00
return sizeof ( x ) ;
}
static auto autoFunc ( ) {
2014-07-09 05:35:03 +08:00
NameFromBase x ; // expected-warning {{lookup into dependent bases}}
2014-07-09 04:05:48 +08:00
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 > ( ) ;
} ;
}
2014-08-15 07:34:52 +08:00
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'}}
}
}
2014-08-25 07:28:47 +08:00
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}}
} ;
}
2015-06-12 05:21:57 +08:00
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}}
} ;
}
2015-06-13 05:23:23 +08:00
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'}}
}
2016-05-25 05:23:54 +08:00
// 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}}
2016-05-31 14:21:27 +08:00
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}}
} ;
}