aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/dcl.dcl
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/dcl.dcl')
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp33
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp94
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp144
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp63
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp28
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp212
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp83
7 files changed, 656 insertions, 1 deletions
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
new file mode 100644
index 000000000000..00d109e67516
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
@@ -0,0 +1,33 @@
+// RUN: clang -fsyntax-only -verify %s
+
+namespace test0 {
+ namespace ns0 {
+ class tag;
+ int tag();
+ }
+
+ namespace ns1 {
+ using ns0::tag;
+ }
+
+ namespace ns2 {
+ using ns0::tag;
+ }
+
+ using ns1::tag;
+ using ns2::tag;
+}
+
+// PR 5752
+namespace test1 {
+ namespace ns {
+ void foo();
+ }
+
+ using ns::foo;
+ void foo(int);
+
+ namespace ns {
+ using test1::foo;
+ }
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
new file mode 100644
index 000000000000..b4302d5b4b90
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
@@ -0,0 +1,94 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++03 [namespace.udecl]p11:
+// If a function declaration in namespace scope or block scope has
+// the same name and the same parameter types as a function
+// introduced by a using-declaration, the program is
+// ill-formed. [Note: two using-declarations may introduce functions
+// with the same name and the same parameter types. If, for a call
+// to an unqualified function name, function overload resolution
+// selects the functions introduced by such using-declarations, the
+// function call is ill-formed.
+
+namespace test0 {
+ namespace ns { void foo(); } // expected-note {{target of using declaration}}
+ int foo(); // expected-note {{conflicting declaration}}
+ using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}}
+}
+
+namespace test1 {
+ namespace ns { void foo(); } // expected-note {{target of using declaration}}
+ using ns::foo; //expected-note {{using declaration}}
+ int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+}
+
+namespace test2 {
+ namespace ns { void foo(); } // expected-note 2 {{target of using declaration}}
+ void test0() {
+ int foo(); // expected-note {{conflicting declaration}}
+ using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}}
+ }
+
+ void test1() {
+ using ns::foo; //expected-note {{using declaration}}
+ int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+ }
+}
+
+namespace test3 {
+ namespace ns { void foo(); } // expected-note 2 {{target of using declaration}}
+ class Test0 {
+ void test() {
+ int foo(); // expected-note {{conflicting declaration}}
+ using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}}
+ }
+ };
+
+ class Test1 {
+ void test() {
+ using ns::foo; //expected-note {{using declaration}}
+ int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+ }
+ };
+}
+
+namespace test4 {
+ namespace ns { void foo(); } // expected-note 2 {{target of using declaration}}
+ template <typename> class Test0 {
+ void test() {
+ int foo(); // expected-note {{conflicting declaration}}
+ using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}}
+ }
+ };
+
+ template <typename> class Test1 {
+ void test() {
+ using ns::foo; //expected-note {{using declaration}}
+ int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+ }
+ };
+}
+
+// FIXME: we should be able to diagnose both of these, but we can't.
+// ...I'm actually not sure why we can diagnose either of them; it's
+// probably a bug.
+namespace test5 {
+ namespace ns { void foo(int); } // expected-note {{target of using declaration}}
+ template <typename T> class Test0 {
+ void test() {
+ int foo(T);
+ using ns::foo;
+ }
+ };
+
+ template <typename T> class Test1 {
+ void test() {
+ using ns::foo; // expected-note {{using declaration}}
+ int foo(T); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+ }
+ };
+
+ template class Test0<int>;
+ template class Test1<int>; // expected-note {{in instantiation of member function}}
+}
+
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
new file mode 100644
index 000000000000..4cbe1be056e4
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
@@ -0,0 +1,144 @@
+// RUN: clang-cc -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> _) {}
+
+// 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>(); }
+ };
+
+ struct Derived2 : Base {
+ template <int n> Opaque<2> foo() { return Opaque<2>(); }
+ using Base::foo;
+ };
+
+ struct Derived3 : Base {
+ using Base::foo;
+ template <class T> Opaque<3> foo() { return Opaque<3>(); }
+ };
+
+ struct Derived4 : Base {
+ template <class T> Opaque<3> foo() { return Opaque<3>(); }
+ using Base::foo;
+ };
+
+ void test() {
+ expect<0>(Base().foo<int>());
+ expect<1>(Base().foo<0>());
+ expect<0>(Derived1().foo<int>());
+ expect<2>(Derived1().foo<0>());
+ expect<0>(Derived2().foo<int>());
+ expect<2>(Derived2().foo<0>());
+ expect<3>(Derived3().foo<int>());
+ expect<1>(Derived3().foo<0>());
+ expect<3>(Derived4().foo<int>());
+ expect<1>(Derived4().foo<0>());
+ }
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
new file mode 100644
index 000000000000..1a05aae3afd6
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp
@@ -0,0 +1,63 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++03 [namespace.udecl]p3:
+// For the purpose of overload resolution, the functions which are
+// introduced by a using-declaration into a derived class will be
+// treated as though they were members of the derived class. In
+// particular, the implicit this parameter shall be treated as if it
+// were a pointer to the derived class rather than to the base
+// class. This has no effect on the type of the function, and in all
+// other respects the function remains a member of the base class.
+
+namespace test0 {
+ struct Opaque0 {};
+ struct Opaque1 {};
+
+ struct Base {
+ Opaque0 test0(int*);
+ Opaque0 test1(const int*);
+ Opaque0 test2(int*);
+ Opaque0 test3(int*) const;
+ };
+
+ struct Derived : Base {
+ using Base::test0;
+ Opaque1 test0(const int*);
+
+ using Base::test1;
+ Opaque1 test1(int*);
+
+ using Base::test2;
+ Opaque1 test2(int*) const;
+
+ using Base::test3;
+ Opaque1 test3(int*);
+ };
+
+ void test0() {
+ Opaque0 a = Derived().test0((int*) 0);
+ Opaque1 b = Derived().test0((const int*) 0);
+ }
+
+ void test1() {
+ Opaque1 a = Derived().test1((int*) 0);
+ Opaque0 b = Derived().test1((const int*) 0);
+ }
+
+ void test2() {
+ Opaque0 a = ((Derived*) 0)->test2((int*) 0);
+ Opaque1 b = ((const Derived*) 0)->test2((int*) 0);
+ }
+
+ void test3() {
+ Opaque1 a = ((Derived*) 0)->test3((int*) 0);
+ Opaque0 b = ((const Derived*) 0)->test3((int*) 0);
+ }
+}
+
+// Things to test:
+// member operators
+// conversion operators
+// call operators
+// call-surrogate conversion operators
+// everything, but in dependent contexts
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
index d701f885fba1..8257330dcf35 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -std=c++0x -fsyntax-only -verify %s
// C++0x N2914.
struct B {
@@ -18,3 +18,29 @@ class D2 : public B {
using B::x;
using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}}
};
+
+namespace test1 {
+ struct Base {
+ int foo();
+ };
+
+ struct Unrelated {
+ int foo();
+ };
+
+ struct Subclass : Base {
+ };
+
+ namespace InnerNS {
+ int foo();
+ }
+
+ // We should be able to diagnose these without instantiation.
+ template <class T> struct C : Base {
+ using InnerNS::foo; // expected-error {{not a class}}
+ using Base::bar; // expected-error {{no member named 'bar'}}
+ using Unrelated::foo; // expected-error {{not a base class}}
+ using C::foo; // expected-error {{refers to its own class}}
+ using Subclass::foo; // expected-error {{not a base class}}
+ };
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
new file mode 100644
index 000000000000..bf314c41b5fb
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
@@ -0,0 +1,212 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++03 [namespace.udecl]p4:
+// A using-declaration used as a member-declaration shall refer to a
+// member of a base class of the class being defined, shall refer to
+// a member of an anonymous union that is a member of a base class
+// of the class being defined, or shall refer to an enumerator for
+// an enumeration type that is a member of a base class of the class
+// being defined.
+
+// There is no directly analogous paragraph in C++0x, and the feature
+// works sufficiently differently there that it needs a separate test.
+
+namespace test0 {
+ namespace NonClass {
+ typedef int type;
+ struct hiding {};
+ int hiding;
+ static union { double union_member; };
+ enum tagname { enumerator };
+ }
+
+ class Test0 {
+ using NonClass::type; // expected-error {{not a class}}
+ using NonClass::hiding; // expected-error {{not a class}}
+ using NonClass::union_member; // expected-error {{not a class}}
+ using NonClass::enumerator; // expected-error {{not a class}}
+ };
+}
+
+struct Opaque0 {};
+
+namespace test1 {
+ struct A {
+ typedef int type;
+ struct hiding {}; // expected-note {{previous use is here}}
+ Opaque0 hiding;
+ union { double union_member; };
+ enum tagname { enumerator };
+ };
+
+ struct B : A {
+ using A::type;
+ using A::hiding;
+ using A::union_member;
+ using A::enumerator;
+ using A::tagname;
+
+ void test0() {
+ type t = 0;
+ }
+
+ void test1() {
+ typedef struct A::hiding local;
+ struct hiding _ = local();
+ }
+
+ void test2() {
+ union hiding _; // expected-error {{tag type that does not match previous}}
+ }
+
+ void test3() {
+ char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+ }
+
+ void test4() {
+ enum tagname _ = enumerator;
+ }
+
+ void test5() {
+ Opaque0 _ = hiding;
+ }
+ };
+}
+
+namespace test2 {
+ struct A {
+ typedef int type;
+ struct hiding {}; // expected-note {{previous use is here}}
+ int hiding;
+ union { double union_member; };
+ enum tagname { enumerator };
+ };
+
+ template <class T> struct B : A {
+ using A::type;
+ using A::hiding;
+ using A::union_member;
+ using A::enumerator;
+ using A::tagname;
+
+ void test0() {
+ type t = 0;
+ }
+
+ void test1() {
+ typedef struct A::hiding local;
+ struct hiding _ = local();
+ }
+
+ void test2() {
+ union hiding _; // expected-error {{tag type that does not match previous}}
+ }
+
+ void test3() {
+ char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+ }
+
+ void test4() {
+ enum tagname _ = enumerator;
+ }
+
+ void test5() {
+ Opaque0 _ = hiding;
+ }
+ };
+}
+
+namespace test3 {
+ struct hiding {};
+
+ template <class T> struct A {
+ typedef int type; // expected-note {{target of using declaration}}
+ struct hiding {};
+ Opaque0 hiding; // expected-note {{target of using declaration}}
+ union { double union_member; }; // expected-note {{target of using declaration}}
+ enum tagname { enumerator }; // expected-note 2 {{target of using declaration}}
+ };
+
+ template <class T> struct B : A<T> {
+ using A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}}
+ using A<T>::hiding;
+ using A<T>::union_member;
+ using A<T>::enumerator;
+ using A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}}
+
+ // FIXME: re-enable these when the various bugs involving tags are fixed
+#if 0
+ void test1() {
+ typedef struct A<T>::hiding local;
+ struct hiding _ = local();
+ }
+
+ void test2() {
+ typedef struct A<T>::hiding local;
+ union hiding _ = local();
+ }
+#endif
+
+ void test3() {
+ char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+ }
+
+#if 0
+ void test4() {
+ enum tagname _ = enumerator;
+ }
+#endif
+
+ void test5() {
+ Opaque0 _ = hiding;
+ }
+ };
+
+ template struct B<int>; // expected-note {{in instantiation}}
+
+ template <class T> struct C : A<T> {
+ using typename A<T>::type;
+ using typename A<T>::hiding; // expected-error {{'typename' keyword used on a non-type}}
+ using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}}
+ using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}}
+
+ void test6() {
+ type t = 0;
+ }
+
+ void test7() {
+ Opaque0 _ = hiding; // expected-error {{expected '(' for function-style cast or type construction}}
+ }
+ };
+
+ template struct C<int>; // expected-note {{in instantiation}}
+}
+
+namespace test4 {
+ struct Base {
+ int foo();
+ };
+
+ struct Unrelated {
+ int foo();
+ };
+
+ struct Subclass : Base {
+ };
+
+ namespace InnerNS {
+ int foo();
+ }
+
+ // We should be able to diagnose these without instantiation.
+ template <class T> struct C : Base {
+ using InnerNS::foo; // expected-error {{not a class}}
+ using Base::bar; // expected-error {{no member named 'bar'}}
+ using Unrelated::foo; // expected-error {{not a base class}}
+ using C::foo; // legal in C++03
+ using Subclass::foo; // legal in C++03
+
+ int bar(); //expected-note {{target of using declaration}}
+ using C::bar; // expected-error {{refers to its own class}}
+ };
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp
new file mode 100644
index 000000000000..bf0f330777d1
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp
@@ -0,0 +1,83 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct Opaque0 {};
+struct Opaque1 {};
+
+// Redeclarations are okay in a namespace.
+namespace test0 {
+ namespace ns {
+ void foo(Opaque0); // expected-note 2 {{candidate function}}
+ }
+
+ using ns::foo;
+ using ns::foo;
+
+ void test0() {
+ foo(Opaque1()); // expected-error {{no matching function for call}}
+ }
+
+ namespace ns {
+ void foo(Opaque1);
+ }
+
+ void test1() {
+ foo(Opaque1()); // expected-error {{no matching function for call}}
+ }
+
+ using ns::foo;
+
+ void test2() {
+ foo(Opaque1());
+ }
+
+ using ns::foo;
+}
+
+// Make sure we handle transparent contexts the same way.
+namespace test1 {
+ namespace ns {
+ void foo(Opaque0); // expected-note 2 {{candidate function}}
+ }
+
+ extern "C++" {
+ using ns::foo;
+ }
+
+ void test0() {
+ foo(Opaque1()); // expected-error {{no matching function for call}}
+ }
+
+ namespace ns {
+ void foo(Opaque1);
+ }
+
+ void test1() {
+ foo(Opaque1()); // expected-error {{no matching function for call}}
+ }
+
+ extern "C++" {
+ using ns::foo;
+ }
+
+ void test2() {
+ foo(Opaque1());
+ }
+}
+
+// Make sure we detect invalid redeclarations that can't be detected
+// until template instantiation.
+namespace test2 {
+ template <class T> struct Base {
+ typedef Base type;
+ void foo();
+ };
+
+ template <class T> struct Derived : Base<T> {
+ // These are invalid redeclarations, detectable only after
+ // instantiation.
+ using Base<T>::foo; // expected-note {{previous using decl}}
+ using Base<T>::type::foo; //expected-error {{redeclaration of using decl}}
+ };
+
+ template struct Derived<int>; // expected-note {{in instantiation of template class}}
+}