diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-12-15 18:49:47 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-12-15 18:49:47 +0000 |
commit | 77212133072dc40f070a280af8217032f55a9eb4 (patch) | |
tree | 2fd5819f49caecc5f520219b6b9254fe94ebb138 /test/CXX | |
parent | 4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa (diff) | |
download | FreeBSD-src-77212133072dc40f070a280af8217032f55a9eb4.zip FreeBSD-src-77212133072dc40f070a280af8217032f55a9eb4.tar.gz |
Update clang to 91430.
Diffstat (limited to 'test/CXX')
19 files changed, 1240 insertions, 2 deletions
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp new file mode 100644 index 0000000..ae5590c --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// FIXME: embellish + +namespace test0 { + namespace A { + class Foo { + }; + + void foo(const Foo &foo); + } + + class Test { + enum E { foo = 0 }; + + void test() { + foo(A::Foo()); // expected-error {{not a function}} + } + }; +} diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp new file mode 100644 index 0000000..c752cec --- /dev/null +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp @@ -0,0 +1,44 @@ +// RUN: clang-cc -fsyntax-only -verify %s +#include <stddef.h> + +struct A { + void *operator new(size_t); +}; + +namespace NS { + void *operator new(size_t);; // expected-error {{'operator new' cannot be declared inside a namespace}} +} + +static void *operator new(size_t); // expected-error {{'operator new' cannot be declared static in global scope}} + +struct B { + void operator new(size_t); // expected-error {{'operator new' must return type 'void *'}} +}; + +struct C { + void *operator new(); // expected-error {{'operator new' must have at least one parameter}} +}; + +struct D { + void *operator new(bool); // expected-error {{'operator new' takes type size_t}} +}; + +struct E { + void *operator new(size_t = 0); // expected-error {{parameter of 'operator new' cannot have a default argument}} +}; + +struct F { + template<typename T> void *operator new(size_t, int); +}; + +struct G { + template<typename T> T operator new(size_t, int); // expected-error {{'operator new' cannot have a dependent return type; use 'void *' instead}} +}; + +struct H { + template<typename T> void *operator new(T, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}} +}; + +struct I { + template<typename T> void *operator new(size_t); // expected-error {{'operator new' template must have at least two parameters}} +}; diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp new file mode 100644 index 0000000..04af5bc --- /dev/null +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A { + void operator delete(void*); +}; + +namespace NS { + void operator delete(void *); // expected-error {{'operator delete' cannot be declared inside a namespace}} +} + +static void operator delete(void *); // expected-error {{'operator delete' cannot be declared static in global scope}} diff --git a/test/CXX/class.access/class.access.dcl/p1.cpp b/test/CXX/class.access/class.access.dcl/p1.cpp new file mode 100644 index 0000000..043a9bf --- /dev/null +++ b/test/CXX/class.access/class.access.dcl/p1.cpp @@ -0,0 +1,199 @@ +// RUN: clang-cc -fsyntax-only -verify + +// This is just the test for [namespace.udecl]p4 with 'using' +// uniformly stripped out. + +// 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 { + NonClass::type; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + NonClass::hiding; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + NonClass::union_member; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + NonClass::enumerator; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + }; +} + +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 { + A::type; // expected-warning {{access declarations are deprecated}} + A::hiding; // expected-warning {{access declarations are deprecated}} + A::union_member; // expected-warning {{access declarations are deprecated}} + A::enumerator; // expected-warning {{access declarations are deprecated}} + A::tagname; // expected-warning {{access declarations are deprecated}} + + 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 { + A::type; // expected-warning {{access declarations are deprecated}} + A::hiding; // expected-warning {{access declarations are deprecated}} + A::union_member; // expected-warning {{access declarations are deprecated}} + A::enumerator; // expected-warning {{access declarations are deprecated}} + A::tagname; // expected-warning {{access declarations are deprecated}} + + 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; + union { double union_member; }; + enum tagname { enumerator }; // expected-note {{target of using declaration}} + }; + + template <class T> struct B : A<T> { + A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}} // expected-warning {{access declarations are deprecated}} + A<T>::hiding; // expected-warning {{access declarations are deprecated}} + A<T>::union_member; // expected-warning {{access declarations are deprecated}} + A<T>::enumerator; // expected-warning {{access declarations are deprecated}} + A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}} // expected-warning {{access declarations are deprecated}} + + // 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}} +} + +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 { + InnerNS::foo; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + Base::bar; // expected-error {{no member named 'bar'}} expected-warning {{access declarations are deprecated}} + Unrelated::foo; // expected-error {{not a base class}} expected-warning {{access declarations are deprecated}} + C::foo; // legal in C++03 // expected-warning {{access declarations are deprecated}} + Subclass::foo; // legal in C++03 // expected-warning {{access declarations are deprecated}} + + int bar(); //expected-note {{target of using declaration}} + C::bar; // expected-error {{refers to its own class}} expected-warning {{access declarations are deprecated}} + }; +} + diff --git a/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp b/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp new file mode 100644 index 0000000..b90661d --- /dev/null +++ b/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp @@ -0,0 +1,93 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// [class.mfct.non-static]p3: +// When an id-expression (5.1) that is not part of a class member +// access syntax (5.2.5) and not used to form a pointer to member +// (5.3.1) is used in the body of a non-static member function of +// class X, if name lookup (3.4.1) resolves the name in the +// id-expression to a non-static non-type member of some class C, +// the id-expression is transformed into a class member access +// expression (5.2.5) using (*this) (9.3.2) as the +// postfix-expression to the left of the . operator. [ Note: if C is +// not X or a base class of X, the class member access expression is +// ill-formed. --end note] Similarly during name lookup, when an +// unqualified-id (5.1) used in the definition of a member function +// for class X resolves to a static member, an enumerator or a +// nested type of class X or of a base class of X, the +// unqualified-id is transformed into a qualified-id (5.1) in which +// the nested-name-specifier names the class of the member function. + +namespace test0 { + class A { + int data_member; + int instance_method(); + static int static_method(); + + bool test() { + return data_member + instance_method() < static_method(); + } + }; +} + +namespace test1 { + struct Opaque1 {}; struct Opaque2 {}; struct Opaque3 {}; + + struct A { + void foo(Opaque1); // expected-note {{candidate}} + void foo(Opaque2); // expected-note {{candidate}} + void test(); + }; + + struct B : A { + + }; + + void A::test() { + B::foo(Opaque1()); + B::foo(Opaque2()); + B::foo(Opaque3()); // expected-error {{no matching member function}} + } +} + +namespace test2 { + class Unrelated { + void foo(); + }; + + template <class T> struct B; + template <class T> struct C; + + template <class T> struct A { + void foo(); + + void test0() { + Unrelated::foo(); // expected-error {{call to non-static member function without an object argument}} + } + + void test1() { + B<T>::foo(); + } + + static void test2() { + B<T>::foo(); // expected-error {{call to non-static member function without an object argument}} + } + + void test3() { + C<T>::foo(); // expected-error {{no member named 'foo'}} + } + }; + + template <class T> struct B : A<T> { + }; + + template <class T> struct C { + }; + + int test() { + A<int> a; + a.test0(); // no instantiation note here, decl is ill-formed + a.test1(); + a.test2(); // expected-note {{in instantiation}} + a.test3(); // expected-note {{in instantiation}} + } +} 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 0000000..00d109e --- /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 0000000..b4302d5 --- /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 0000000..4cbe1be --- /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 0000000..1a05aae --- /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 d701f88..8257330 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 0000000..bf314c4 --- /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 0000000..bf0f330 --- /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}} +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp new file mode 100644 index 0000000..f62b425 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f0() { + int &ir = { 17 }; // expected-error{{reference to type 'int' cannot bind to an initializer list}} +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp new file mode 100644 index 0000000..66fa2d1 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s +int g(int); +void f() { + int i; + int& r = i; + r = 1; + int* p = &r; + int &rr=r; + int (&rg)(int) = g; + rg(i); + int a[3]; + int (&ra)[3] = a; + ra[1] = i; +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp new file mode 100644 index 0000000..54840f5 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int& r1; // expected-error{{declaration of reference variable 'r1' requires an initializer}} +extern int& r2; diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp new file mode 100644 index 0000000..5d34345 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -0,0 +1,53 @@ +// RUN: clang-cc -ast-dump %s 2>&1 | FileCheck %s + +// CHECK: example0 +void example0() { + double d = 2.0; + // CHECK: double &rd = + // CHECK-NEXT: DeclRefExpr + double &rd = d; + // CHECK: double const &rcd = + // CHECK-NEXT: ImplicitCastExpr{{.*}}'double const' <NoOp> + const double &rcd = d; +} + +struct A { }; +struct B : A { } b; + +// CHECK: example1 +void example1() { + // CHECK: struct A &ra = + // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> lvalue + A &ra = b; + // CHECK: struct A const &rca = + // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> + const A& rca = b; +} + +extern B f(); + +struct X { + operator B(); +} x; + +// CHECK: example2 +void example2() { + // CHECK: struct A const &rca = + // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> + // CHECK: CallExpr{{.*}}struct B + const A &rca = f(); + // CHECK: struct A const &r = + // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase> + // CHECK: CXXMemberCallExpr{{.*}}'struct B' + const A& r = x; +} + +// CHECK: example3 +void example3() { + // CHECK: double const &rcd2 = + // CHECK: ImplicitCastExpr{{.*}}<IntegralToFloating> + const double& rcd2 = 2; +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp new file mode 100644 index 0000000..5fa1fff --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp @@ -0,0 +1,129 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct Base { }; // expected-note{{candidate function}} +struct Derived : Base { }; // expected-note{{candidate function}} +struct Unrelated { }; +struct Derived2 : Base { }; +struct Diamond : Derived, Derived2 { }; + +struct ConvertibleToBaseRef { + operator Base&() const; +}; + +struct ConvertibleToDerivedRef { + operator Derived&() const; +}; + +struct ConvertibleToBothDerivedRef { + operator Derived&(); // expected-note{{candidate function}} + operator Derived2&(); // expected-note{{candidate function}} +}; + +struct ConvertibleToIntRef { + operator int&(); +}; + +struct ConvertibleToBase { + operator Base() const; +}; + +struct ConvertibleToDerived { + operator Derived() const; +}; + +struct ConvertibleToBothDerived { + operator Derived(); // expected-note{{candidate function}} + operator Derived2(); // expected-note{{candidate function}} +}; + +struct ConvertibleToInt { + operator int(); +}; + +template<typename T> T create(); + +// First bullet: lvalue references binding to lvalues (the simple cases). +void bind_lvalue_to_lvalue(Base b, Derived d, + const Base bc, const Derived dc, + Diamond diamond, + int i) { + // Reference-compatible + Base &br1 = b; + Base &br2 = d; + Derived &dr1 = d; + Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'struct Derived' cannot bind to a value of unrelated type 'struct Base'}} + Base &br3 = bc; // expected-error{{drops qualifiers}} + Base &br4 = dc; // expected-error{{drops qualifiers}} + Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'struct Diamond' to base class 'struct Base'}} + int &ir = i; + long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}} +} + +void bind_lvalue_quals(volatile Base b, volatile Derived d, + volatile const Base bvc, volatile const Derived dvc, + volatile const int ivc) { + volatile Base &bvr1 = b; + volatile Base &bvr2 = d; + volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Base const volatile' drops qualifiers}} + volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Derived const volatile' drops qualifiers}} + + volatile int &ir = ivc; // expected-error{{binding of reference to type 'int volatile' to a value of type 'int const volatile' drops qualifiers}} +} + +void bind_lvalue_to_rvalue() { + Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Base'}} + Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Derived'}} + + int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} +} + +void bind_lvalue_to_unrelated(Unrelated ur) { + Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a value of unrelated type 'struct Unrelated'}} +} + +void bind_lvalue_to_conv_lvalue() { + // Not reference-related, but convertible + Base &nbr1 = ConvertibleToBaseRef(); + Base &nbr2 = ConvertibleToDerivedRef(); + Derived &ndr1 = ConvertibleToDerivedRef(); + int &ir = ConvertibleToIntRef(); +} + +void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) { + Derived &dr1 = both; + Base &br1 = both; // expected-error{{error: conversion from 'struct ConvertibleToBothDerivedRef' to 'struct Base' is ambiguous}} +} + +struct IntBitfield { + int i : 17; // expected-note{{bit-field is declared here}} +}; + +void test_bitfield(IntBitfield ib) { + int & ir1 = (ib.i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} +} + +// Second bullet: const lvalue reference binding to an rvalue with +// similar type (both of which are class types). +void bind_const_lvalue_to_rvalue() { + const Base &br1 = create<Base>(); + const Base &br2 = create<Derived>(); + const Derived &dr1 = create<Base>(); // expected-error{{no viable conversion}} + + const Base &br3 = create<const Base>(); + const Base &br4 = create<const Derived>(); + + const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'struct Base const' to a value of type 'struct Base const volatile' drops qualifiers}} + const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'struct Base const' to a value of type 'struct Derived const volatile' drops qualifiers}} + + const int &ir = create<int>(); +} + +// Second bullet: const lvalue reference binds to the result of a conversion. +void bind_const_lvalue_to_class_conv_temporary() { + const Base &br1 = ConvertibleToBase(); + const Base &br2 = ConvertibleToDerived(); +} +void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) { + const Derived &dr1 = both; + const Base &br1 = both; // expected-error{{error: conversion from 'struct ConvertibleToBothDerived' to 'struct Base const' is ambiguous}} +} diff --git a/test/CXX/special/class.free/p6.cpp b/test/CXX/special/class.free/p6.cpp index 8334817..b082b85 100644 --- a/test/CXX/special/class.free/p6.cpp +++ b/test/CXX/special/class.free/p6.cpp @@ -2,7 +2,7 @@ #include <stddef.h> struct A { - void operator delete(size_t) { + void operator delete(void*) { (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} } void operator delete[](void*) { diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp index 883cb71..0665304 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -10,3 +10,15 @@ template<> template<> class A<int>::B<double>; template<> template<> void A<char>::B<char>::mf(); template<> void A<char>::B<int>::mf(); // expected-error{{requires 'template<>'}} + +namespace test1 { + template <class> class A { + static int foo; + static int bar; + }; + typedef A<int> AA; + + template <> int AA::foo = 0; // expected-error {{cannot use typedef}} + int AA::bar = 1; // expected-error {{cannot use typedef}} expected-error {{template specialization requires 'template<>'}} + int A<float>::bar = 2; // expected-error {{template specialization requires 'template<>'}} +} |