196 lines
5.4 KiB
C++
196 lines
5.4 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
|
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
|
|
|
// C++03 [namespace.udecl]p12:
|
|
// When a using-declaration brings names from a base class into a
|
|
// derived class scope, member functions in the derived class
|
|
// override and/or hide member functions with the same name and
|
|
// parameter types in a base class (rather than conflicting).
|
|
|
|
template <unsigned n> struct Opaque {};
|
|
template <unsigned n> void expect(Opaque<n> _) {} // expected-note 4 {{candidate function template not viable}}
|
|
|
|
// PR5727
|
|
// This just shouldn't crash.
|
|
namespace test0 {
|
|
template<typename> struct RefPtr { };
|
|
template<typename> struct PtrHash {
|
|
static void f() { }
|
|
};
|
|
template<typename T> struct PtrHash<RefPtr<T> > : PtrHash<T*> {
|
|
using PtrHash<T*>::f;
|
|
static void f() { f(); }
|
|
};
|
|
}
|
|
|
|
// Simple hiding.
|
|
namespace test1 {
|
|
struct Base {
|
|
Opaque<0> foo(Opaque<0>);
|
|
Opaque<0> foo(Opaque<1>);
|
|
Opaque<0> foo(Opaque<2>);
|
|
};
|
|
|
|
// using before decls
|
|
struct Test0 : Base {
|
|
using Base::foo;
|
|
Opaque<1> foo(Opaque<1>);
|
|
Opaque<1> foo(Opaque<3>);
|
|
|
|
void test0() { Opaque<0> _ = foo(Opaque<0>()); }
|
|
void test1() { Opaque<1> _ = foo(Opaque<1>()); }
|
|
void test2() { Opaque<0> _ = foo(Opaque<2>()); }
|
|
void test3() { Opaque<1> _ = foo(Opaque<3>()); }
|
|
};
|
|
|
|
// using after decls
|
|
struct Test1 : Base {
|
|
Opaque<1> foo(Opaque<1>);
|
|
Opaque<1> foo(Opaque<3>);
|
|
using Base::foo;
|
|
|
|
void test0() { Opaque<0> _ = foo(Opaque<0>()); }
|
|
void test1() { Opaque<1> _ = foo(Opaque<1>()); }
|
|
void test2() { Opaque<0> _ = foo(Opaque<2>()); }
|
|
void test3() { Opaque<1> _ = foo(Opaque<3>()); }
|
|
};
|
|
|
|
// using between decls
|
|
struct Test2 : Base {
|
|
Opaque<1> foo(Opaque<0>);
|
|
using Base::foo;
|
|
Opaque<1> foo(Opaque<2>);
|
|
Opaque<1> foo(Opaque<3>);
|
|
|
|
void test0() { Opaque<1> _ = foo(Opaque<0>()); }
|
|
void test1() { Opaque<0> _ = foo(Opaque<1>()); }
|
|
void test2() { Opaque<1> _ = foo(Opaque<2>()); }
|
|
void test3() { Opaque<1> _ = foo(Opaque<3>()); }
|
|
};
|
|
}
|
|
|
|
// Crazy dependent hiding.
|
|
namespace test2 {
|
|
struct Base {
|
|
void foo(int);
|
|
};
|
|
|
|
template <typename T> struct Derived1 : Base {
|
|
using Base::foo;
|
|
void foo(T);
|
|
|
|
void testUnresolved(int i) { foo(i); }
|
|
};
|
|
|
|
void test0(int i) {
|
|
Derived1<int> d1;
|
|
d1.foo(i);
|
|
d1.testUnresolved(i);
|
|
}
|
|
|
|
// Same thing, except with the order of members reversed.
|
|
template <typename T> struct Derived2 : Base {
|
|
void foo(T);
|
|
using Base::foo;
|
|
|
|
void testUnresolved(int i) { foo(i); }
|
|
};
|
|
|
|
void test1(int i) {
|
|
Derived2<int> d2;
|
|
d2.foo(i);
|
|
d2.testUnresolved(i);
|
|
}
|
|
}
|
|
|
|
// Hiding of member templates.
|
|
namespace test3 {
|
|
struct Base {
|
|
template <class T> Opaque<0> foo() { return Opaque<0>(); }
|
|
template <int n> Opaque<1> foo() { return Opaque<1>(); }
|
|
};
|
|
|
|
struct Derived1 : Base {
|
|
using Base::foo;
|
|
template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}}
|
|
};
|
|
|
|
struct Derived2 : Base {
|
|
template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}}
|
|
using Base::foo;
|
|
};
|
|
|
|
struct Derived3 : Base {
|
|
using Base::foo;
|
|
template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}}
|
|
};
|
|
|
|
struct Derived4 : Base {
|
|
template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}}
|
|
using Base::foo;
|
|
};
|
|
|
|
void test() {
|
|
expect<0>(Base().foo<int>());
|
|
expect<1>(Base().foo<0>());
|
|
expect<0>(Derived1().foo<int>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
|
|
expect<2>(Derived1().foo<0>());
|
|
expect<0>(Derived2().foo<int>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
|
|
expect<2>(Derived2().foo<0>());
|
|
expect<3>(Derived3().foo<int>());
|
|
expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
|
|
expect<3>(Derived4().foo<int>());
|
|
expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
|
|
}
|
|
}
|
|
|
|
// PR7384: access control for member templates.
|
|
namespace test4 {
|
|
class Base {
|
|
protected:
|
|
template<typename T> void foo(T);
|
|
template<typename T> void bar(T); // expected-note {{declared protected here}}
|
|
};
|
|
|
|
struct Derived : Base {
|
|
using Base::foo;
|
|
};
|
|
|
|
void test() {
|
|
Derived d;
|
|
d.foo<int>(3);
|
|
d.bar<int>(3); // expected-error {{'bar' is a protected member}}
|
|
}
|
|
}
|
|
|
|
namespace test5 {
|
|
struct Derived;
|
|
struct Base {
|
|
void operator=(const Derived&);
|
|
};
|
|
struct Derived : Base {
|
|
// Hidden by implicit derived class operator.
|
|
using Base::operator=;
|
|
};
|
|
void f(Derived d) {
|
|
d = d;
|
|
}
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
namespace test6 {
|
|
struct Derived;
|
|
struct Base {
|
|
void operator=(Derived&&);
|
|
};
|
|
struct Derived : Base {
|
|
// Hidden by implicit derived class operator.
|
|
using Base::operator=;
|
|
};
|
|
void f(Derived d) {
|
|
d = Derived();
|
|
}
|
|
}
|
|
#endif
|