diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
| commit | ecb7e5c8afe929ee38155db94de6b084ec32a645 (patch) | |
| tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /test/CXX | |
| parent | 5044f5c816adfd5cba17f1adee1a10127296d0bf (diff) | |
Notes
Diffstat (limited to 'test/CXX')
26 files changed, 794 insertions, 35 deletions
diff --git a/test/CXX/basic/basic.def.odr/p1-var.cpp b/test/CXX/basic/basic.def.odr/p1-var.cpp new file mode 100644 index 000000000000..892f546ee545 --- /dev/null +++ b/test/CXX/basic/basic.def.odr/p1-var.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++ [basic.def.odr]p1: +// No translation unit shall contain more than one definition of any +// variable, [...]. + +// Bad: in C++, these are both definitions. None of that C99 tentative stuff. +int i; // expected-note {{previous}} +int i; // expected-error {{redefinition}} + +// OK: decl + def +extern int j; +int j; + +// OK: def + decl +int k; +extern int k; + +// Bad. The important thing here is that we don't emit the diagnostic twice. +int l = 1; // expected-note {{previous}} +int l = 2; // expected-error {{redefinition}} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp b/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp index 76b6e2b57465..8126d28562ae 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp @@ -15,4 +15,4 @@ namespace A { } class Ident<int> GlobalIdent; -union Ident<int> GlobalIdent; // expected-error {{ tag type that does not match }} +union Ident<int> GlobalIdent2; // expected-error {{ tag type that does not match }} diff --git a/test/CXX/class.access/class.access.base/p1.cpp b/test/CXX/class.access/class.access.base/p1.cpp index fd0d9f68e1e2..1bbcedb9a1e7 100644 --- a/test/CXX/class.access/class.access.base/p1.cpp +++ b/test/CXX/class.access/class.access.base/p1.cpp @@ -54,13 +54,13 @@ namespace test0 { // of the base class are accessible as protected members of the // derived class. namespace test1 { - class Base { // expected-note 6 {{constrained by protected inheritance}} - public: int pub; static int spub; // expected-note 2 {{constrained by protected inheritance}} + class Base { + public: int pub; static int spub; protected: int prot; static int sprot; // expected-note 4 {{declared protected here}} private: int priv; static int spriv; // expected-note 8 {{declared private here}} }; - class Test : protected Base { + class Test : protected Base { // expected-note 6 {{declared protected here}} expected-note 8 {{constrained by protected inheritance here}} void test() { pub++; spub++; @@ -79,19 +79,19 @@ namespace test1 { }; void test(Test *t) { - t->pub++; // expected-error {{protected member}} + t->pub++; // expected-error {{protected member}} expected-error {{protected base class}} t->spub++; // expected-error {{protected member}} - t->prot++; // expected-error {{protected member}} + t->prot++; // expected-error {{protected member}} expected-error {{protected base class}} t->sprot++; // expected-error {{protected member}} - t->priv++; // expected-error {{private member}} + t->priv++; // expected-error {{private member}} expected-error {{protected base class}} t->spriv++; // expected-error {{private member}} // Two possible errors here: one for Base, one for the member - t->Base::pub++; // expected-error {{protected member}} + t->Base::pub++; // expected-error {{protected member}} expected-error {{protected base class}} t->Base::spub++; // expected-error {{protected member}} - t->Base::prot++; // expected-error 2 {{protected member}} + t->Base::prot++; // expected-error 2 {{protected member}} expected-error {{protected base class}} t->Base::sprot++; // expected-error 2 {{protected member}} - t->Base::priv++; // expected-error {{protected member}} expected-error {{private member}} + t->Base::priv++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{protected base class}} t->Base::spriv++; // expected-error {{protected member}} expected-error {{private member}} } } @@ -102,21 +102,20 @@ namespace test1 { // the base class are accessible as private members of the derived // class. namespace test2 { - class Base { //expected-note 6 {{constrained by private inheritance}} + class Base { public: - int pub; // expected-note {{constrained by private inheritance}} - static int spub; // expected-note {{constrained by private inheritance}} + int pub; + static int spub; protected: - int prot; // expected-note {{constrained by private inheritance}} \ - // expected-note {{declared protected here}} - static int sprot; // expected-note {{constrained by private inheritance}} \ - // expected-note {{declared protected here}} + int prot; // expected-note {{declared protected here}} + static int sprot; // expected-note {{declared protected here}} private: int priv; // expected-note 4 {{declared private here}} static int spriv; // expected-note 4 {{declared private here}} }; - class Test : private Base { // expected-note 6 {{'private' inheritance specifier here}} + class Test : private Base { // expected-note 6 {{declared private here}} \ + // expected-note 10 {{constrained by private inheritance here}} void test() { pub++; spub++; @@ -135,18 +134,18 @@ namespace test2 { }; void test(Test *t) { - t->pub++; // expected-error {{private member}} expected-error {{inaccessible base class}} + t->pub++; // expected-error {{private member}} expected-error {{private base class}} t->spub++; // expected-error {{private member}} - t->prot++; // expected-error {{private member}} expected-error {{inaccessible base class}} + t->prot++; // expected-error {{private member}} expected-error {{private base class}} t->sprot++; // expected-error {{private member}} - t->priv++; // expected-error {{private member}} expected-error {{inaccessible base class}} + t->priv++; // expected-error {{private member}} expected-error {{private base class}} t->spriv++; // expected-error {{private member}} - t->Base::pub++; // expected-error {{private member}} expected-error {{inaccessible base class}} + t->Base::pub++; // expected-error {{private member}} expected-error {{private base class}} t->Base::spub++; // expected-error {{private member}} - t->Base::prot++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{inaccessible base class}} + t->Base::prot++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{private base class}} t->Base::sprot++; // expected-error {{protected member}} expected-error {{private member}} - t->Base::priv++; // expected-error 2 {{private member}} expected-error {{inaccessible base class}} + t->Base::priv++; // expected-error 2 {{private member}} expected-error {{private base class}} t->Base::spriv++; // expected-error 2 {{private member}} } } diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp new file mode 100644 index 000000000000..7aa614cd8b1a --- /dev/null +++ b/test/CXX/class.access/p4.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s + +// C++0x [class.access]p4: + +// Access control is applied uniformly to all names, whether the +// names are referred to from declarations or expressions. In the +// case of overloaded function names, access control is applied to +// the function selected by overload resolution. + +class Public {} PublicInst; +class Protected {} ProtectedInst; +class Private {} PrivateInst; + +namespace test0 { + class A { + public: + void foo(Public&); + protected: + void foo(Protected&); // expected-note 2 {{declared protected here}} + private: + void foo(Private&); // expected-note 2 {{declared private here}} + }; + + void test(A *op) { + op->foo(PublicInst); + op->foo(ProtectedInst); // expected-error {{'foo' is a protected member}} + op->foo(PrivateInst); // expected-error {{'foo' is a private member}} + + void (A::*a)(Public&) = &A::foo; + void (A::*b)(Protected&) = &A::foo; // expected-error {{'foo' is a protected member}} + void (A::*c)(Private&) = &A::foo; // expected-error {{'foo' is a private member}} + } +} + +// Member operators. +namespace test1 { + class A { + public: + void operator+(Public&); + void operator[](Public&); + void operator()(Public&); + typedef void (*PublicSurrogate)(Public&); + operator PublicSurrogate() const; + protected: + void operator+(Protected&); // expected-note {{declared protected here}} + void operator[](Protected&); // expected-note {{declared protected here}} + void operator()(Protected&); // expected-note {{declared protected here}} + typedef void (*ProtectedSurrogate)(Protected&); + operator ProtectedSurrogate() const; // expected-note {{declared protected here}} + private: + void operator+(Private&); // expected-note {{declared private here}} + void operator[](Private&); // expected-note {{declared private here}} + void operator()(Private&); // expected-note {{declared private here}} + void operator-(); // expected-note {{declared private here}} + typedef void (*PrivateSurrogate)(Private&); + operator PrivateSurrogate() const; // expected-note {{declared private here}} + }; + void operator+(const A &, Public&); + void operator+(const A &, Protected&); + void operator+(const A &, Private&); + void operator-(const A &); + + void test(A &a, Public &pub, Protected &prot, Private &priv) { + a + pub; + a + prot; // expected-error {{'operator+' is a protected member}} + a + priv; // expected-error {{'operator+' is a private member}} + a[pub]; + a[prot]; // expected-error {{'operator[]' is a protected member}} + a[priv]; // expected-error {{'operator[]' is a private member}} + a(pub); + a(prot); // expected-error {{'operator()' is a protected member}} + a(priv); // expected-error {{'operator()' is a private member}} + -a; // expected-error {{'operator-' is a private member}} + + const A &ca = a; + ca + pub; + ca + prot; + ca + priv; + -ca; + // These are all surrogate calls + ca(pub); + ca(prot); // expected-error {{'operator void (*)(class Protected &)' is a protected member}} + ca(priv); // expected-error {{'operator void (*)(class Private &)' is a private member}} + } +} + +// Implicit constructor calls. +namespace test2 { + class A { + private: + A(); // expected-note {{declared private here}} + + static A foo; + }; + + A a; // expected-error {{calling a private constructor}} + A A::foo; // okay +} + +// Implicit destructor calls. +namespace test3 { + class A{ + private: + ~A(); // expected-note 3 {{declared private here}} + static A foo; + }; + + A a; // expected-error {{'~A' is a private member}} + A A::foo; + + void foo(A param) { // expected-error {{'~A' is a private member}} + A local; // expected-error {{'~A' is a private member}} + } +} diff --git a/test/CXX/class.access/p6.cpp b/test/CXX/class.access/p6.cpp new file mode 100644 index 000000000000..aaf510a6d11f --- /dev/null +++ b/test/CXX/class.access/p6.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s + +// C++0x [class.access]p6: +// All access controls in [class.access] affect the ability to +// access a class member name from a particular scope. For purposes +// of access control, the base-specifiers of a class and the +// definitions of class members that appear outside of the class +// definition are considered to be within the scope of that +// class. In particular, access controls apply as usual to member +// names accessed as part of a function return type, even though it +// is not possible to determine the access privileges of that use +// without first parsing the rest of the function +// declarator. Similarly, access control for implicit calls to the +// constructors, the conversion functions, or the destructor called +// to create and destroy a static data member is performed as if +// these calls appeared in the scope of the member's class. + +struct Public {}; struct Protected {}; struct Private {}; + +namespace test0 { + class A { + typedef int type; // expected-note {{declared private here}} + type foo(); + }; + + A::type foo() { } // expected-error {{'type' is a private member}} + A::type A::foo() { } +} + +// conversion decls +namespace test1 { + class A { + public: + A(); + operator Public (); + A(Public); + protected: + operator Protected (); // expected-note {{declared protected here}} + A(Protected); // expected-note {{declared protected here}} + private: + operator Private (); // expected-note {{declared private here}} + A(Private); // expected-note {{declared private here}} + }; + + void test() { + A a; + Public pub = a; + Protected prot = a; // expected-error {{'operator Protected' is a protected member}} + Private priv = a; // expected-error {{'operator Private' is a private member}} + A apub = pub; + A aprot = prot; // expected-error {{protected constructor}} + A apriv = priv; // expected-error {{private constructor}} + } +} diff --git a/test/CXX/class/class.local/p2.cpp b/test/CXX/class/class.local/p2.cpp index 56ff1e53a493..8d281a57e137 100644 --- a/test/CXX/class/class.local/p2.cpp +++ b/test/CXX/class/class.local/p2.cpp @@ -3,9 +3,9 @@ struct A { }; void f() { - struct B : private A {}; // expected-note{{'private' inheritance specifier here}} + struct B : private A {}; // expected-note{{declared private here}} B b; - A *a = &b; // expected-error{{conversion from 'struct B' to inaccessible base class 'struct A'}} + A *a = &b; // expected-error{{cannot cast 'struct B' to its private base class 'struct A'}} } diff --git a/test/CXX/conv/conv.mem/p4.cpp b/test/CXX/conv/conv.mem/p4.cpp new file mode 100644 index 000000000000..1ecbc47ffbb8 --- /dev/null +++ b/test/CXX/conv/conv.mem/p4.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s + +struct Base { + int data; + int method(); +}; +int (Base::*data_ptr) = &Base::data; +int (Base::*method_ptr)() = &Base::method; + +namespace test0 { + struct Derived : Base {}; + void test() { + int (Derived::*d) = data_ptr; + int (Derived::*m)() = method_ptr; + } +} + +// Can't be inaccessible. +namespace test1 { + struct Derived : private Base {}; // expected-note 2 {{declared private here}} + void test() { + int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'struct Base' to 'struct test1::Derived'}} + int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'struct Base' to 'struct test1::Derived'}} + } +}; + +// Can't be ambiguous. +namespace test2 { + struct A : Base {}; + struct B : Base {}; + struct Derived : A, B {}; + void test() { + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test2::Derived'}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test2::Derived'}} + } +} + +// Can't be virtual. +namespace test3 { + struct Derived : virtual Base {}; + void test() { + int (Derived::*d) = data_ptr; // expected-error {{conversion from pointer to member of class 'struct Base' to pointer to member of class 'struct test3::Derived' via virtual base 'struct Base' is not allowed}} + int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'struct Base' to pointer to member of class 'struct test3::Derived' via virtual base 'struct Base' is not allowed}} + } +} + +// Can't be virtual even if there's a non-virtual path. +namespace test4 { + struct A : Base {}; + struct Derived : Base, virtual A {}; + void test() { + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test4::Derived'}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'struct Base' to pointer to member of derived class 'struct test4::Derived'}} + } +} + +// PR6254: don't get thrown off by a virtual base. +namespace test5 { + struct A {}; + struct Derived : Base, virtual A {}; + void test() { + int (Derived::*d) = data_ptr; + int (Derived::*m)() = method_ptr; + } +} diff --git a/test/CXX/conv/conv.qual/pr6089.cpp b/test/CXX/conv/conv.qual/pr6089.cpp new file mode 100644 index 000000000000..ae75ec41bd8f --- /dev/null +++ b/test/CXX/conv/conv.qual/pr6089.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +bool is_char_ptr( const char* ); + +template< class T > + long is_char_ptr( T /* r */ ); + +// Note: the const here does not lead to a qualification conversion +template< class T > + void make_range( T* const r, bool ); + +template< class T > + void make_range( T& r, long ); + +void first_finder( const char*& Search ) +{ + make_range( Search, is_char_ptr(Search) ); +} diff --git a/test/CXX/dcl.dcl/dcl.enum/p5.cpp b/test/CXX/dcl.dcl/dcl.enum/p5.cpp new file mode 100644 index 000000000000..f26062416cbf --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.enum/p5.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s +template<typename T> int force_same(T, T); + +// C++ [dcl.enum]p5: +// [...] If the underlying type is not fixed, the type of each enumerator is +// the type of its initializing value: +// - If an initializer is specified for an enumerator, the initializing +// value has the same type as the expression. +enum Bullet1 { + Bullet1Val1 = 'a', + Bullet1Val2 = 10u, + Bullet1Val1IsChar = sizeof(force_same(Bullet1Val1, char(0))), + Bullet1Val2IsUnsigned = sizeof(force_same(Bullet1Val2, unsigned(0))) +}; + +// - If no initializer is specified for the first enumerator, the +// initializing value has an unspecified integral type. +enum Bullet2 { + Bullet2Val, + Bullet2ValIsInt = sizeof(force_same(Bullet2Val, int(0))) +}; + +// - Otherwise the type of the initializing value is the same as the type +// of the initializing value of the preceding enumerator unless the +// incremented value is not representable in that type, in which case the +// type is an unspecified integral type sufficient to contain the +// incremented value. If no such type exists, the program is ill-formed. +enum Bullet3a { + Bullet3aVal1 = 17, + Bullet3aVal2, + Bullet3aVal2IsInt = sizeof(force_same(Bullet3aVal2, int(0))), + Bullet3aVal3 = 2147483647, + Bullet3aVal3IsInt = sizeof(force_same(Bullet3aVal3, int(0))), + Bullet3aVal4, + Bullet3aVal4IsUnsigned = sizeof(force_same(Bullet3aVal4, 0ul)) +}; + +enum Bullet3b { + Bullet3bVal1 = 17u, + Bullet3bVal2, + Bullet3bVal2IsInt = sizeof(force_same(Bullet3bVal2, 0u)), + Bullet3bVal3 = 2147483647u, + Bullet3bVal3IsInt = sizeof(force_same(Bullet3bVal3, 0u)), + Bullet3bVal4, + Bullet3bVal4IsUnsigned = sizeof(force_same(Bullet3bVal4, 0ul)) +}; + +enum Bullet3c { + Bullet3cVal1 = 0xFFFFFFFFFFFFFFFEull, + Bullet3cVal2, + Bullet3cVal3 // expected-warning{{not representable}} +}; + +// Following the closing brace of an enum-specifier, each enumerator has the +// type of its enumeration. +int array0[sizeof(force_same(Bullet3bVal3, Bullet3b(0)))? 1 : -1]; diff --git a/test/CXX/dcl.dcl/dcl.link/p7.cpp b/test/CXX/dcl.dcl/dcl.link/p7.cpp new file mode 100644 index 000000000000..bd9ff3c3665c --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.link/p7.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +struct X { }; + +// CHECK: @x1 = global %struct.X zeroinitializer +// CHECK: @x4 = global %struct.X zeroinitializer +// CHECK: @x2 = external global %struct.X +// CHECK: @x3 = external global %struct.X +extern "C" { + + + X x1; +} + +extern "C" X x2; + +extern X x3; + +X x4; + +X& get(int i) { + if (i == 1) + return x1; + else if (i == 2) + return x2; + else if (i == 3) + return x3; + else + return x4; +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp index 16a09d836d16..fcc1334b1506 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -verify %s -// XFAIL: * class A { public: @@ -7,7 +6,11 @@ public: explicit operator int(); // expected-warning {{explicit conversion functions are a C++0x extension}} - explicit void f0(); // expected-error {{'explicit' cannot only be applied to constructor or conversion function}} + explicit void f0(); // expected-error {{'explicit' can only be applied to a constructor or conversion function}} + + operator bool(); }; -explicit A::A() { } // expected-error {{'explicit' cannot be specified outside class definition}} +explicit A::A() { } // expected-error {{'explicit' can only be specified inside the class definition}} +explicit A::operator bool() { return false; } // expected-warning {{explicit conversion functions are a C++0x extension}}\ + // expected-error {{'explicit' can only be specified inside the class definition}} 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 index cf3db5175fa4..d9c5d014014a 100644 --- 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 @@ -68,17 +68,23 @@ void bind_lvalue_quals(volatile Base b, volatile Derived d, 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}} + + const volatile Base &bcvr1 = b; + const volatile Base &bcvr2 = d; } 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'}} + const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a temporary of type 'struct Base'}} + const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'struct Base const volatile' 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'}} + const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a value of unrelated type 'struct Unrelated'}} } void bind_lvalue_to_conv_lvalue() { diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp new file mode 100644 index 000000000000..cf529098dfe4 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5909 { + struct Foo { + int x : 20; + }; + + bool Test(const int& foo); + + const Foo f = { 0 }; // It compiles without the 'const'. + bool z = Test(f.x); +} diff --git a/test/CXX/dcl.decl/dcl.init/p6.cpp b/test/CXX/dcl.decl/dcl.init/p6.cpp new file mode 100644 index 000000000000..f627a199eca6 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/p6.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: Very incomplete! + +// If a program calls for the default initialization of an object of a +// const-qualified type T, T shall be a class type with a +// user-provided default constructor. +struct NoUserDefault { }; +struct HasUserDefault { HasUserDefault(); }; + +void test_const_default_init() { + const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}} + const HasUserDefault x2; + const int x3; // expected-error{{default initialization of an object of const type 'int const'}} +} diff --git a/test/CXX/dcl.decl/dcl.name/p1.cpp b/test/CXX/dcl.decl/dcl.name/p1.cpp new file mode 100644 index 000000000000..7586007cc7b3 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.name/p1.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace pr6200 { + struct v {}; + struct s { + int i; + operator struct v() { return v(); }; + }; + + void f() + { + // Neither of these is a declaration. + (void)new struct s; + (void)&s::operator struct v; + } +} diff --git a/test/CXX/expr/p8.cpp b/test/CXX/expr/p8.cpp index cc834d9dc8d8..2f6c094301ee 100644 --- a/test/CXX/expr/p8.cpp +++ b/test/CXX/expr/p8.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s int a0; -const volatile int a1; +const volatile int a1 = 2; int a2[16]; int a3(); diff --git a/test/CXX/lex/lex.literal/lex.ccon/p1.cpp b/test/CXX/lex/lex.literal/lex.ccon/p1.cpp new file mode 100644 index 000000000000..7b65f7ee8320 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ccon/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Check types of char literals +extern char a; +extern __typeof('a') a; +extern int b; +extern __typeof('asdf') b; +extern wchar_t c; +extern __typeof(L'a') c; diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp new file mode 100644 index 000000000000..83365a2a082c --- /dev/null +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.arg.nontype]p1: +// +// A template-argument for a non-type, non-template template-parameter shall +// be one of: +// -- an integral constant expression; or +// -- the name of a non-type template-parameter ; or +namespace non_type_tmpl_param { + template <int N> struct X0 { X0(); }; + template <int N> X0<N>::X0() { } + template <int* N> struct X1 { X1(); }; + template <int* N> X1<N>::X1() { } + template <int& N> struct X3 { X3(); }; + template <int& N> X3<N>::X3() { } + template <int (*F)(int)> struct X4 { X4(); }; + template <int (*F)(int)> X4<F>::X4() { } + template <typename T, int (T::* M)(int)> struct X5 { X5(); }; + template <typename T, int (T::* M)(int)> X5<T, M>::X5() { } +} + +// -- the address of an object or function with external linkage, including +// function templates and function template-ids but excluding non-static +// class members, expressed as & id-expression where the & is optional if +// the name refers to a function or array, or if the corresponding +// template-parameter is a reference; or +namespace addr_of_obj_or_func { + template <int* p> struct X0 { }; + template <int (*fp)(int)> struct X1 { }; + // FIXME: Add reference template parameter tests. + + int i = 42; + int iarr[10]; + int f(int i); + template <typename T> T f_tmpl(T t); + void test() { + X0<&i> x0a; + X0<iarr> x0b; + X1<&f> x1a; + X1<f> x1b; + X1<f_tmpl> x1c; + X1<f_tmpl<int> > x1d; + } +} + +// -- a constant expression that evaluates to a null pointer value (4.10); or +// -- a constant expression that evaluates to a null member pointer value +// (4.11); or +// -- a pointer to member expressed as described in 5.3.1. + +namespace bad_args { + template <int* N> struct X0 { }; + int i = 42; + X0<&i + 2> x0a; // expected-error{{non-type template argument does not refer to any declaration}} + int* iptr = &i; + X0<iptr> x0b; // FIXME: This should not be accepted. +} diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp new file mode 100644 index 000000000000..458aff2f0232 --- /dev/null +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.arg.nontype] p5: +// The following conversions are performed on each expression used as +// a non-type template-argument. If a non-type template-argument cannot be +// converted to the type of the corresponding template-parameter then the +// program is ill-formed. +// -- for a non-type template-parameter of integral or enumeration type, +// integral promotions (4.5) and integral conversions (4.7) are applied. +// -- for a non-type template-parameter of type pointer to object, +// qualification conversions (4.4) and the array-to-pointer conversion +// (4.2) are applied; if the template-argument is of type +// std::nullptr_t, the null pointer conversion (4.10) is applied. +namespace pointer_to_object_parameters { + // PR6226 + struct Str { + Str(const char *); + }; + + template<const char *s> + struct A { + Str get() { return s; } + }; + + char hello[6] = "Hello"; + extern const char world[6]; + const char world[6] = "world"; + void test() { + (void)A<hello>().get(); + (void)A<world>().get(); + } + + class X { + public: + X(); + X(int, int); + operator int() const; + }; + + template<X const *Ptr> struct A2; + + X *X_ptr; + X an_X; + X array_of_Xs[10]; + A2<X_ptr> *a12; + A2<array_of_Xs> *a13; + A2<&an_X> *a13_2; + A2<(&an_X)> *a13_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}} + + // PR6244 + struct X1 {} X1v; + template <X1*> struct X2 { }; + template <X1* Value> struct X3 : X2<Value> { }; + struct X4 : X3<&X1v> { }; +} + +// -- For a non-type template-parameter of type reference to object, no +// conversions apply. The type referred to by the reference may be more +// cv-qualified than the (otherwise identical) type of the +// template-argument. The template-parameter is bound directly to the +// template-argument, which shall be an lvalue. +namespace reference_parameters { + template <int& N> struct S0 { }; // expected-note 3 {{template parameter is declared here}} + template <const int& N> struct S1 { }; // expected-note 2 {{template parameter is declared here}} + template <volatile int& N> struct S2 { }; // expected-note 2 {{template parameter is declared here}} + template <const volatile int& N> struct S3 { }; + int i; + extern const int ci; + volatile int vi; + extern const volatile int cvi; + void test() { + S0<i> s0; + S0<ci> s0c; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'int const' ignores qualifiers}} + S0<vi> s0v; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'int volatile' ignores qualifiers}} + S0<cvi> s0cv; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'int const volatile' ignores qualifiers}} + + S1<i> s1; + S1<ci> s1c; + S1<vi> s1v; // expected-error{{reference binding of non-type template parameter of type 'int const &' to template argument of type 'int volatile' ignores qualifiers}} + S1<cvi> s1cv; // expected-error{{reference binding of non-type template parameter of type 'int const &' to template argument of type 'int const volatile' ignores qualifiers}} + + S2<i> s2; + S2<ci> s2c; // expected-error{{reference binding of non-type template parameter of type 'int volatile &' to template argument of type 'int const' ignores qualifiers}} + S2<vi> s2v; + S2<cvi> s2cv; // expected-error{{reference binding of non-type template parameter of type 'int volatile &' to template argument of type 'int const volatile' ignores qualifiers}} + + S3<i> s3; + S3<ci> s3c; + S3<vi> s3v; + S3<cvi> s3cv; + } + + namespace PR6250 { + template <typename T, const T &ref> void inc() { + ref++; // expected-error{{read-only variable is not assignable}} + } + + template<typename T, const T &ref> void bind() { + T &ref2 = ref; // expected-error{{drops qualifiers}} + } + + int counter; + void test() { + inc<int, counter>(); // expected-note{{instantiation of}} + bind<int, counter>(); // expected-note{{instantiation of}} + } + } +} + +// -- For a non-type template-parameter of type pointer to function, the +// function-to-pointer conversion (4.3) is applied; if the +// template-argument is of type std::nullptr_t, the null pointer +// conversion (4.10) is applied. If the template-argument represents +// a set of overloaded functions (or a pointer to such), the matching +// function is selected from the set (13.4). +// -- For a non-type template-parameter of type reference to function, no +// conversions apply. If the template-argument represents a set of +// overloaded functions, the matching function is selected from the set +// (13.4). +// -- For a non-type template-parameter of type pointer to member function, +// if the template-argument is of type std::nullptr_t, the null member +// pointer conversion (4.11) is applied; otherwise, no conversions +// apply. If the template-argument represents a set of overloaded member +// functions, the matching member function is selected from the set +// (13.4). +// -- For a non-type template-parameter of type pointer to data member, +// qualification conversions (4.4) are applied; if the template-argument +// is of type std::nullptr_t, the null member pointer conversion (4.11) +// is applied. diff --git a/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/test/CXX/temp/temp.decls/temp.mem/p5.cpp index 098ffa4dec75..b0078d4bdb6d 100644 --- a/test/CXX/temp/temp.decls/temp.mem/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.mem/p5.cpp @@ -55,7 +55,7 @@ template double Foo::As2(); // Partial ordering with conversion function templates. struct X0 { template<typename T> operator T*() { - T x; + T x = 1; x = 17; // expected-error{{read-only variable is not assignable}} } diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp index 8fb736ca0313..95f9640a0b43 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate function}} +template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} void g() { f<int,char*,double>("aa",3.0); diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp index bcfb71c987eb..1b7310f00055 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -15,7 +15,8 @@ void test_f1(int *ip, float fv) { f1(ip, fv); } -template<typename T> void f2(T*, T*); // expected-note 2 {{candidate function}} +// TODO: this diagnostic can and should improve +template<typename T> void f2(T*, T*); // expected-note 2 {{candidate template ignored: failed template argument deduction}} struct ConvToIntPtr { operator int*() const; diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp new file mode 100644 index 000000000000..6edf079b3524 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + template<class T> void apply(T x, void (*f)(T)) { f(x); } // expected-note 2 {{failed template argument deduction}}\ + // expected-note {{no overload of 'temp2' matching 'void (*)(int)'}} + + template<class A> void temp(A); + void test0() { + // okay: deduce T=int from first argument, A=int during overload + apply(0, &temp); + apply(0, &temp<>); + + // okay: deduce T=int from first and second arguments + apply(0, &temp<int>); + + // deduction failure: T=int from first, T=long from second + apply(0, &temp<long>); // expected-error {{no matching function for call to 'apply'}} + } + + void over(int); + int over(long); + + void test1() { + // okay: deductions match + apply(0, &over); + + // deduction failure: deduced T=long from first argument, T=int from second + apply(0L, &over); // expected-error {{no matching function for call to 'apply'}} + } + + void over(short); + + void test2() { + // deduce T=int from first arg, second arg is undeduced context, + // pick correct overload of 'over' during overload resolution for 'apply' + apply(0, &over); + } + + template<class A, class B> B temp2(A); + void test3() { + // deduce T=int from first arg, A=int B=void during overload resolution + apply(0, &temp2); + apply(0, &temp2<>); + apply(0, &temp2<int>); + + // overload failure + apply(0, &temp2<long>); // expected-error {{no matching function for call to 'apply'}} + } +} + +namespace test1 { + template<class T> void invoke(void (*f)(T)) { f(T()); } // expected-note 6 {{couldn't infer template argument}} \ + // expected-note {{failed template argument deduction}} + + template<class T> void temp(T); + void test0() { + // deduction failure: overload has template => undeduced context + invoke(&temp); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp<>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp<int>); + } + + void over(int); + int over(long); + + void test1() { + // okay: only one overload matches + invoke(&over); + } + + void over(short); + + void test2() { + // deduction failure: overload has multiple matches => undeduced context + invoke(&over); // expected-error {{no matching function for call to 'invoke'}} + } + + template<class A, class B> B temp2(A); + void test3() { + // deduction failure: overload has template => undeduced context + // (even though partial application temp2<int> could in theory + // let us infer T=int) + invoke(&temp2); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<>); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<int>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp2<int, void>); + + // overload failure + invoke(&temp2<int, int>); // expected-error {{no matching function for call to 'invoke'}} + } +} diff --git a/test/CXX/temp/temp.names/p4.cpp b/test/CXX/temp/temp.names/p4.cpp new file mode 100644 index 000000000000..103a1bd537f8 --- /dev/null +++ b/test/CXX/temp/temp.names/p4.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct meta { + template<typename U> + struct apply { + typedef U* type; + }; +}; + +template<typename T, typename U> +void f(typename T::template apply<U>::type); + +void test_f(int *ip) { + f<meta, int>(ip); +} diff --git a/test/CXX/temp/temp.res/temp.local/p1.cpp b/test/CXX/temp/temp.res/temp.local/p1.cpp new file mode 100644 index 000000000000..ed534a462767 --- /dev/null +++ b/test/CXX/temp/temp.res/temp.local/p1.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.local]p1: +// Like normal (non-template) classes, class templates have an +// injected-class-name (Clause 9). The injected-class-name can be used with +// or without a template-argument-list. When it is used without +// a template-argument-list, it is equivalent to the injected-class-name +// followed by the template-parameters of the class template enclosed in <>. + +template <typename T> struct X0 { + X0(); + ~X0(); + X0 f(const X0&); +}; + +// Test non-type template parameters. +template <int N1, const int& N2, const int* N3> struct X1 { + X1(); + ~X1(); + X1 f(const X1& x1a) { X1 x1b(x1a); return x1b; } +}; + +// When it is used with a template-argument-list, it refers to the specified +// class template specialization, which could be the current specialization +// or another specialization. +// FIXME: Test this clause. + +int i = 42; +int* iptr = &i; +void test() { + X0<int> x0; (void)x0; + X1<42, i, iptr> x1; (void)x1; +} 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 3b5b5afa8ed9..88cfc5d7c397 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -18,7 +18,18 @@ namespace test1 { }; 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<>'}} + template <> int AA::foo = 0; + int AA::bar = 1; // expected-error {{template specialization requires 'template<>'}} int A<float>::bar = 2; // expected-error {{template specialization requires 'template<>'}} + + template <> class A<double> { + public: + static int foo; // expected-note{{attempt to specialize}} + static int bar; + }; + + typedef A<double> AB; + template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}} \ + // expected-error{{does not specialize}} + int AB::bar = 1; } |
