diff options
Diffstat (limited to 'test/CXX')
173 files changed, 5420 insertions, 444 deletions
diff --git a/test/CXX/basic/basic.link/p9.cpp b/test/CXX/basic/basic.link/p9.cpp index bd16b02d7badf..680c93db2e29a 100644 --- a/test/CXX/basic/basic.link/p9.cpp +++ b/test/CXX/basic/basic.link/p9.cpp @@ -6,6 +6,5 @@ namespace N { } // expected-note{{here}} // First bullet: two names with external linkage that refer to // different kinds of entities. void f() { - int N(); // expected-error{{redefinition}} + int N(); // expected-error{{redefinition}} expected-warning{{interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} } - diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp index cee7c02420333..f5ad68b75bdf1 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp @@ -46,7 +46,7 @@ namespace M { int g(N::X); // expected-note{{candidate function}} void test(N::X x) { - g(x); // expected-error{{call to 'g' is ambiguous; candidates are:}} + g(x); // expected-error{{call to 'g' is ambiguous}} int i = (g)(x); int g(N::X); diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp index 15d86b7740c4c..32dd75ad49a87 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp @@ -44,7 +44,7 @@ namespace Test { A::A() + A::A(); B::B() + B::B(); C::C() + C::C(); - D::D() + D::D(); // expected-error {{ invalid operands to binary expression ('D::D' and 'D::D') }} + D::D() + D::D(); // expected-error {{invalid operands to binary expression ('D::D' and 'D::D')}} } } diff --git a/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp b/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp index c35af1def2085..c20728332704a 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp @@ -36,7 +36,7 @@ void resolves_to_different() { Value v; // The fact that the next line is a warning rather than an error is an // extension. - v.set<double>(3.2); // expected-warning{{lookup of 'set' in member access expression is ambiguous; using member of 'Value' [-Wambiguous-member-template]}} + v.set<double>(3.2); // expected-warning{{lookup of 'set' in member access expression is ambiguous; using member of 'Value'}} } { int set; // Non-template. @@ -62,3 +62,28 @@ namespace rdar9915664 { } }; } + +namespace PR11856 { + template<typename T> T end(T); + + template <typename T> + void Foo() { + T it1; + if (it1->end < it1->end) { + } + } + + template<typename T> T *end(T*); + + class X { }; + template <typename T> + void Foo2() { + T it1; + if (it1->end < it1->end) { + } + + X *x; + if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}} + } + } +} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2f.cpp b/test/CXX/basic/basic.start/basic.start.main/p2f.cpp index a3d6a79a4fa0a..ea5a752a191cd 100644 --- a/test/CXX/basic/basic.start/basic.start.main/p2f.cpp +++ b/test/CXX/basic/basic.start/basic.start.main/p2f.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -void // expected-error {{error: 'main' must return 'int'}} -main( // expected-error {{error: first parameter of 'main' (argument count) must be of type 'int'}} +void // expected-error {{'main' must return 'int'}} +main( // expected-error {{first parameter of 'main' (argument count) must be of type 'int'}} float a ) { } diff --git a/test/CXX/basic/basic.start/basic.start.main/p2i.cpp b/test/CXX/basic/basic.start/basic.start.main/p2i.cpp new file mode 100644 index 0000000000000..db8da3c4e7c03 --- /dev/null +++ b/test/CXX/basic/basic.start/basic.start.main/p2i.cpp @@ -0,0 +1,6 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -x c++ %s -std=c++11 -fsyntax-only -verify +// RUN: not %clang_cc1 -x c++ %t -std=c++11 -fixit +// RUN: %clang_cc1 -x c++ %t -std=c++11 -fsyntax-only + +constexpr int main() { } // expected-error{{'main' is not allowed to be declared constexpr}} diff --git a/test/CXX/basic/basic.types/p10.cpp b/test/CXX/basic/basic.types/p10.cpp index 3b438d15f28bf..83b910b60640d 100644 --- a/test/CXX/basic/basic.types/p10.cpp +++ b/test/CXX/basic/basic.types/p10.cpp @@ -5,21 +5,40 @@ struct NonLiteral { NonLiteral(); }; // A type is a literal type if it is: // - a scalar type -constexpr int f1(double); +constexpr int f1(double) { return 0; } // - a reference type struct S { S(); }; -constexpr int f2(S &); +constexpr int f2(S &) { return 0; } + +// FIXME: I'm not entirely sure whether the following is legal or not... +struct BeingDefined; +extern BeingDefined beingdefined; +struct BeingDefined { + static constexpr BeingDefined& t = beingdefined; +}; // - a class type that has all of the following properties: +// (implied) - it is complete + +struct Incomplete; +template<class T> struct ClassTemp {}; + +constexpr Incomplete incomplete = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete'}} +constexpr Incomplete incomplete2[] = {}; // expected-error {{constexpr variable cannot have non-literal type 'Incomplete const[]'}} +constexpr ClassTemp<int> classtemplate = {}; +constexpr ClassTemp<int> classtemplate2[] = {}; + // - it has a trivial destructor struct UserProvDtor { - constexpr UserProvDtor(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} + constexpr int f(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} ~UserProvDtor(); // expected-note {{has a user-provided destructor}} }; + struct NonTrivDtor { - constexpr NonTrivDtor(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} + constexpr NonTrivDtor(); + constexpr int f(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} }; struct NonTrivDtorBase { @@ -29,17 +48,16 @@ template<typename T> struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} constexpr DerivedFromNonTrivDtor(); }; -constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} +constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} struct TrivDtor { constexpr TrivDtor(); }; -// FIXME: when building DefinitionData we look at 'isUserProvided' before it's set up! -#if 0 +constexpr int f(TrivDtor) { return 0; } struct TrivDefaultedDtor { constexpr TrivDefaultedDtor(); ~TrivDefaultedDtor() = default; }; -#endif +constexpr int f(TrivDefaultedDtor) { return 0; } // - it is an aggregate type or has at least one constexpr constructor or // constexpr constructor template that is not a copy or move constructor @@ -52,36 +70,41 @@ struct CtorTemplate { template<typename T> constexpr CtorTemplate(T); }; struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} - constexpr CopyCtorOnly(CopyCtorOnly&); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}} + constexpr CopyCtorOnly(CopyCtorOnly&); + constexpr int f(); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}} }; struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} - constexpr MoveCtorOnly(MoveCtorOnly&&); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}} + constexpr MoveCtorOnly(MoveCtorOnly&&); + constexpr int f(); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}} }; template<typename T> -struct CtorArg { // expected-note {{no constexpr constructors other than copy or move constructors}} - constexpr CtorArg(T); // expected-note {{constructor template instantiation is not constexpr because 1st parameter type 'NonLiteral' is not a literal type}} +struct CtorArg { + constexpr CtorArg(T); }; -constexpr int f(CtorArg<int>); -constexpr int f(CtorArg<NonLiteral>); // expected-error {{not a literal type}} +constexpr int f(CtorArg<int>) { return 0; } // ok +constexpr int f(CtorArg<NonLiteral>) { return 0; } // ok, ctor is still constexpr // We have a special-case diagnostic for classes with virtual base classes. struct VBase {}; struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}} struct Derived : HasVBase { - constexpr Derived(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}} + constexpr Derived() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} }; template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} constexpr DerivedFromVBase(); }; -constexpr int f(DerivedFromVBase<HasVBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} +constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} +template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {} +constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}} // - it has all non-static data members and base classes of literal types struct NonLitMember { S s; // expected-note {{has data member 's' of non-literal type 'S'}} }; -constexpr int f(NonLitMember); // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} +constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} struct NonLitBase : S { // expected-note {{base class 'S' of non-literal type}} - constexpr NonLitBase(); // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}} + constexpr NonLitBase(); + constexpr int f() { return 0; } // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}} }; struct LitMemBase : Agg { Agg agg; @@ -91,37 +114,19 @@ struct MemberType { T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}} constexpr MemberType(); }; -constexpr int f(MemberType<int>); -constexpr int f(MemberType<NonLiteral>); // expected-error {{not a literal type}} +constexpr int f(MemberType<int>) { return 0; } +constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}} // - an array of literal type struct ArrGood { Agg agg[24]; double d[12]; TrivDtor td[3]; + TrivDefaultedDtor tdd[3]; }; -constexpr int f(ArrGood); +constexpr int f(ArrGood) { return 0; } struct ArrBad { S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}} }; -constexpr int f(ArrBad); // expected-error {{1st parameter type 'ArrBad' is not a literal type}} - - -// As a non-conforming tweak to the standard, we do not allow a literal type to -// have any mutable data members. -namespace MutableMembers { - struct MM { - mutable int n; // expected-note {{'MM' is not literal because it has a mutable data member}} - }; - constexpr int f(MM); // expected-error {{not a literal type}} - - // Here's one reason why allowing this would be a disaster... - template<int n> struct Id { int k = n; }; - int f() { - // FIXME: correctly check whether the initializer is a constant expression. - constexpr MM m = { 0 }; // desired-error {{must be a constant expression}} - ++m.n; - return Id<m.n>().k; // expected-error {{not an integral constant expression}} - } -} +constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}} diff --git a/test/CXX/class.access/class.protected/p1-cxx11.cpp b/test/CXX/class.access/class.protected/p1-cxx11.cpp new file mode 100644 index 0000000000000..dc9b20d17c0e3 --- /dev/null +++ b/test/CXX/class.access/class.protected/p1-cxx11.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR12497 +namespace test0 { + class A { + protected: + A() {} + A(const A &) {} + ~A() {} + A &operator=(const A &a) { return *this; } + }; + + class B : public A {}; + + void test() { + B b1; + B b2 = b1; + b1 = b2; + } +} diff --git a/test/CXX/class.access/class.protected/p1.cpp b/test/CXX/class.access/class.protected/p1.cpp index 79bb6cd67eab8..c9491e1196f9a 100644 --- a/test/CXX/class.access/class.protected/p1.cpp +++ b/test/CXX/class.access/class.protected/p1.cpp @@ -68,7 +68,7 @@ namespace test1 { namespace test2 { class A { - protected: int x; // expected-note 3 {{object type must derive}} + protected: int x; // expected-note 3 {{can only access this member on an object of type}} static int sx; static void test(A&); }; @@ -103,7 +103,7 @@ namespace test2 { namespace test3 { class B; class A { - protected: int x; // expected-note {{object type must derive}} + protected: int x; //expected-note {{declared protected}} // expected-note {{can only access this member on an object of type}} static int sx; static void test(B&); }; @@ -130,7 +130,7 @@ namespace test3 { (void) b.sx; } void D::test(B &b) { - (void) b.x; + (void) b.x; // expected-error {{'x' is a protected member}} (void) b.sx; } } @@ -138,7 +138,7 @@ namespace test3 { namespace test4 { class C; class A { - protected: int x; // expected-note {{declared}} expected-note 2 {{object type must derive}} + protected: int x; // expected-note 2{{declared protected here}} expected-note{{member is declared here}} static int sx; // expected-note 3{{member is declared here}} static void test(C&); }; @@ -215,7 +215,7 @@ namespace test6 { class Static {}; class A { protected: - void foo(int); // expected-note 3 {{object type must derive}} + void foo(int); // expected-note 3 {{can only access this member on an object of type}} void foo(long); static void foo(Static); @@ -253,7 +253,7 @@ namespace test7 { class Static {}; class A { protected: - void foo(int); // expected-note 3 {{object type must derive}} + void foo(int); // expected-note 3 {{must name member using the type of the current context}} void foo(long); static void foo(Static); @@ -291,7 +291,7 @@ namespace test8 { class Static {}; class A { protected: - void foo(int); // expected-note 3 {{object type must derive}} + void foo(int); // expected-note 3 {{must name member using the type of the current context}} void foo(long); static void foo(Static); @@ -329,7 +329,7 @@ namespace test8 { namespace test9 { class A { // expected-note {{member is declared here}} - protected: int foo(); // expected-note 4 {{declared}} expected-note 2 {{object type must derive}} expected-note {{object type 'test9::A' must derive}} + protected: int foo(); // expected-note 4 {{declared}} expected-note 2 {{can only access this member on an object of type}} expected-note {{member is declared here}} }; class B : public A { // expected-note {{member is declared here}} @@ -423,7 +423,7 @@ namespace test12 { // This friendship is not considered because a public member of A is // inaccessible in C. namespace test13 { - class A { protected: int foo(); }; // expected-note {{object type 'test13::D' must derive from context type 'test13::C'}} + class A { protected: int foo(); }; // expected-note {{can only access this member on an object of type}} class B : private virtual A {}; class C : private B { friend void test(); }; class D : public virtual A {}; @@ -433,3 +433,87 @@ namespace test13 { d.A::foo(); // expected-error {{protected member}} } } + +// PR8058 +namespace test14 { + class A { + protected: + template <class T> void temp(T t); // expected-note {{must name member using the type of the current context}} + + void nontemp(int); // expected-note {{must name member using the type of the current context}} + + template <class T> void ovl_temp(T t); // expected-note {{must name member using the type of the current context}} + void ovl_temp(float); + + void ovl_nontemp(int); // expected-note {{must name member using the type of the current context}} + void ovl_nontemp(float); + + template <class T> void ovl_withtemp(T); + void ovl_withtemp(int); // expected-note {{must name member using the type of the current context}} + }; + + class B : public A { + void use() { + void (A::*ptr)(int); + ptr = &A::temp; // expected-error {{protected member}} + ptr = &A::nontemp; // expected-error {{protected member}} + ptr = &A::ovl_temp; // expected-error {{protected member}} + ptr = &A::ovl_nontemp; // expected-error {{protected member}} + ptr = &A::ovl_withtemp; // expected-error {{protected member}} + } + }; +} + +namespace test15 { + class A { + protected: + A(); // expected-note 2 {{protected constructor can only be used to construct a base class subobject}} + A(const A &); // expected-note {{protected constructor can only be used to construct a base class subobject}} + ~A(); // expected-note 3 {{protected destructor can only be used to destroy a base class subobject}} + }; + + class B : public A { + // The uses here are fine. + B() {} + B(int i) : A() {} + ~B() {} + + // All these uses are bad. + + void test0() { + A a; // expected-error {{protected constructor}} expected-error {{protected destructor}} + } + + A *test1() { + return new A(); // expected-error {{protected constructor}} + } + + void test2(A *a) { + delete a; // expected-error {{protected destructor}} + } + + A test3(A *a) { + return *a; // expected-error {{protected constructor}} + } + + void test4(A *a) { + a->~A(); // expected-error {{protected member}} + } + }; +} + +namespace test16 { + class A { + protected: + ~A(); + }; + + class B : public virtual A { + public: + ~B() {} + }; + + class C : public B { + ~C() {} + }; +} diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index add3635fa63f3..5ad738bebf9cc 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -372,7 +372,7 @@ namespace test15 { int private_foo; // expected-note {{declared private here}} static int private_sfoo; // expected-note {{declared private here}} protected: - int protected_foo; // expected-note 3 {{declared protected here}} // expected-note {{object type must derive from context type 'test15::B<int>'}} + int protected_foo; // expected-note 3 {{declared protected here}} // expected-note {{can only access this member on an object of type 'test15::B<int>'}} static int protected_sfoo; // expected-note 3 {{declared protected here}} int test1(A<int> &a) { @@ -481,7 +481,7 @@ namespace test21 { }; template <class T> class A<T>::Inner {}; class B { - template <class T> class A<T>::Inner; + template <class T> class A<T>::Inner; // expected-error{{non-friend class member 'Inner' cannot have a qualified name}} }; void test() { diff --git a/test/CXX/class.access/p6.cpp b/test/CXX/class.access/p6.cpp index 932b4f42f2a33..fbdc87b24e26a 100644 --- a/test/CXX/class.access/p6.cpp +++ b/test/CXX/class.access/p6.cpp @@ -150,7 +150,7 @@ namespace test6 { class B : A { public_inner a; protected_inner b; - private_inner c; // expected-error {{ 'private_inner' is a private member of 'test6::A'}} + private_inner c; // expected-error {{'private_inner' is a private member of 'test6::A'}} }; } diff --git a/test/CXX/class.derived/class.member.lookup/p6.cpp b/test/CXX/class.derived/class.member.lookup/p6.cpp index 5f4b2a7430e7c..72398819263f6 100644 --- a/test/CXX/class.derived/class.member.lookup/p6.cpp +++ b/test/CXX/class.derived/class.member.lookup/p6.cpp @@ -29,7 +29,7 @@ void D::glorp() { x++; f(); y++; // expected-error{{member 'y' found in multiple base classes of different types}} - g(); // expected-error{{error: member 'g' found in multiple base classes of different types}} + g(); // expected-error{{member 'g' found in multiple base classes of different types}} } // PR6462 diff --git a/test/CXX/class.derived/p1.cpp b/test/CXX/class.derived/p1.cpp new file mode 100644 index 0000000000000..dc5cb2b8c2a38 --- /dev/null +++ b/test/CXX/class.derived/p1.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11 + +// base-clause: +// : base-specifier-list +// base-specifier-list: +// base-specifier ...[opt] +// base-specifier-list , base-specifier ...[opt] +// base-specifier: +// attribute-specifier-seq[opt] base-type-specifier +// attribute-specifier-seq[opt] virtual access-specifier[opt] base-type-specifier +// attribute-specifier-seq[opt] access-specifier virtual[opt] base-type-specifier +// class-or-decltype: +// nested-name-specifier[opt] class-name +// decltype-specifier +// base-type-specifier: +// class-or-decltype +// access-specifier: +// private +// protected +// public + +namespace PR11216 { + struct Base { }; + struct Derived : decltype(Base()) { }; + + int func(); + struct Derived2 : decltype(func()) { }; // expected-error {{base specifier must name a class}} + + template<typename T> + struct Derived3 : decltype(T().foo()) { }; + struct Foo { Base foo(); }; + Derived3<Foo> d; + + struct Derived4 : :: decltype(Base()) { }; // expected-error {{unexpected namespace scope prior to decltype}} + + struct Derived5 : PR11216:: decltype(Base()) { }; // expected-error {{unexpected namespace scope prior to decltype}} + + template<typename T> + struct Derived6 : typename T::foo { }; // expected-error {{'typename' is redundant; base classes are implicitly types}} +} diff --git a/test/CXX/class/class.base/class.base.init/p5-0x.cpp b/test/CXX/class/class.base/class.base.init/p5-0x.cpp new file mode 100644 index 0000000000000..e9aa6da7dc7b9 --- /dev/null +++ b/test/CXX/class/class.base/class.base.init/p5-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// [class.base.init]p5 +// A ctor-initializer may initialize a variant member of the constructor’s +// class. If a ctor-initializer specifies more than one mem-initializer for the +// same member or for the same base class, the ctor-initializer is ill-formed. + +union E { + int a; + int b; + E() : a(1), // expected-note{{previous initialization is here}} + b(2) { // expected-error{{initializing multiple members of union}} + } +}; + +union F { + struct { + int a; + int b; + }; + int c; + F() : a(1), // expected-note{{previous initialization is here}} + b(2), + c(3) { // expected-error{{initializing multiple members of union}} + } +}; diff --git a/test/CXX/class/class.friend/p1-cxx11.cpp b/test/CXX/class/class.friend/p1-cxx11.cpp new file mode 100644 index 0000000000000..235f295d1277d --- /dev/null +++ b/test/CXX/class/class.friend/p1-cxx11.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +class A { + class AInner { + }; + + void a_member(); + friend void A::a_member(); // ok in c++11, ill-formed in c++98 + friend void a_member(); // ok in both, refers to non-member + friend class A::AInner; // ok in c++11, extension in c++98 + friend class AInner; // ok in both, refers to non-member +}; diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index bb1af101d242e..07b3a101c2a95 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -29,36 +29,36 @@ class A { friend class PreDeclared; friend class Outer::Inner; - friend int Outer::Inner::intfield; // expected-error {{ friends can only be classes or functions }} - friend int Outer::Inner::missing_field; //expected-error {{ friends can only be classes or functions }} + friend int Outer::Inner::intfield; // expected-error {{friends can only be classes or functions}} + friend int Outer::Inner::missing_field; //expected-error {{friends can only be classes or functions}} friend int myoperation(float); // okay - friend int myglobal; // expected-error {{ friends can only be classes or functions }} + friend int myglobal; // expected-error {{friends can only be classes or functions}} friend void global_function(); friend void global_c_function(); friend class UndeclaredSoFar; - UndeclaredSoFar x; // expected-error {{ unknown type name 'UndeclaredSoFar' }} + UndeclaredSoFar x; // expected-error {{unknown type name 'UndeclaredSoFar'}} void a_member(); - friend void A::a_member(); // expected-error {{ friends cannot be members of the declaring class }} + friend void A::a_member(); // expected-error {{friends cannot be members of the declaring class}} friend void a_member(); // okay (because we ignore class scopes when looking up friends) friend class A::AInner; // this is okay as an extension friend class AInner; // okay, refers to ::AInner - friend void Derived::missing_member(); // expected-error {{ no function named 'missing_member' with type 'void ()' was found in the specified scope }} + friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}} - friend void Derived::base_member(); // expected-error {{ no function named 'base_member' with type 'void ()' was found in the specified scope }} + friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}} friend int Base::typedeffed_member(); // okay: should look through typedef // These test that the friend is properly not being treated as a // member function. friend A operator|(const A& l, const A& r); // okay - friend A operator|(const A& r); // expected-error {{ overloaded 'operator|' must be a binary operator (has 1 parameter) }} + friend A operator|(const A& r); // expected-error {{overloaded 'operator|' must be a binary operator (has 1 parameter)}} - friend operator bool() const; // expected-error {{ must use a qualified name when declaring a conversion operator as a friend }} \ - // expected-error{{type qualifier is not allowed on this function}} + friend operator bool() const; // expected-error {{must use a qualified name when declaring a conversion operator as a friend}} \ + // expected-error{{non-member function cannot have 'const' qualifier}} typedef void ftypedef(); friend ftypedef typedeffed_function; // okay (because it's not declared as a member) diff --git a/test/CXX/class/class.friend/p6.cpp b/test/CXX/class/class.friend/p6.cpp index 82a90ff82f203..7d7a06419a7a1 100644 --- a/test/CXX/class/class.friend/p6.cpp +++ b/test/CXX/class/class.friend/p6.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -verify %s class A { friend static class B; // expected-error {{'static' is invalid in friend declarations}} diff --git a/test/CXX/class/class.local/p1-0x.cpp b/test/CXX/class/class.local/p1-0x.cpp new file mode 100644 index 0000000000000..49125f5f9b062 --- /dev/null +++ b/test/CXX/class/class.local/p1-0x.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +void f() { + int x = 3; // expected-note{{'x' declared here}} + const int c = 2; + struct C { + int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing function 'f'}} + int cc = c; + }; + (void)[]() mutable { + int x = 3; // expected-note{{'x' declared here}} + struct C { + int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing lambda expression}} + }; + }; + C(); +} + diff --git a/test/CXX/class/class.local/p1.cpp b/test/CXX/class/class.local/p1.cpp index 05ae5c71d15a9..62ade5cb88461 100644 --- a/test/CXX/class/class.local/p1.cpp +++ b/test/CXX/class/class.local/p1.cpp @@ -8,7 +8,7 @@ void f() extern int g(); struct local { - int g() { return x; } // expected-error{{reference to local variable 'x' declared in enclosed function 'f'}} + int g() { return x; } // expected-error{{reference to local variable 'x' declared in enclosing function 'f'}} int h() { return s; } int k() { return :: x; } int l() { return g(); } diff --git a/test/CXX/class/class.local/p3.cpp b/test/CXX/class/class.local/p3.cpp index c24d5d8a09a20..3753790384962 100644 --- a/test/CXX/class/class.local/p3.cpp +++ b/test/CXX/class/class.local/p3.cpp @@ -24,7 +24,7 @@ void f2() { void f3(int a) { // expected-note{{'a' declared here}} struct X { struct Y { - int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosed function 'f3'}} + int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosing function 'f3'}} }; }; } diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp index 7cded23878e62..84885848870e0 100644 --- a/test/CXX/class/class.mem/p13.cpp +++ b/test/CXX/class/class.mem/p13.cpp @@ -17,7 +17,7 @@ struct X1 { // expected-note{{previous use is here}} }; struct X2 { - typedef int X2; // expected-error{{member 'X2' has the same name as its class)}} + typedef int X2; // expected-error{{member 'X2' has the same name as its class}} }; // - every enumerator of every member of class T that is an enumerated type; and diff --git a/test/CXX/class/class.nest/p1-cxx0x.cpp b/test/CXX/class/class.nest/p1-cxx0x.cpp index 0f12579ee4f89..b7a1a48c64f68 100644 --- a/test/CXX/class/class.nest/p1-cxx0x.cpp +++ b/test/CXX/class/class.nest/p1-cxx0x.cpp @@ -9,6 +9,6 @@ class Outer { class Inner { static char a[sizeof(x)]; // okay static char b[sizeof(sx)]; // okay - static char c[sizeof(f)]; // expected-error {{ call to non-static member function without an object argument }} + static char c[sizeof(f)]; // expected-error {{call to non-static member function without an object argument}} }; }; diff --git a/test/CXX/class/class.nest/p1.cpp b/test/CXX/class/class.nest/p1.cpp index 350cc814e9b2f..b0341da7c212b 100644 --- a/test/CXX/class/class.nest/p1.cpp +++ b/test/CXX/class/class.nest/p1.cpp @@ -5,10 +5,10 @@ class Outer { static int sx; int f(); - // C++0x does relax this rule (see 5.1.1.10) in the first case, but we need to enforce it in C++03 mode. + // C++11 does relax this rule (see 5.1.1.10) in the first case, but we need to enforce it in C++03 mode. class Inner { - static char a[sizeof(x)]; // expected-error {{ invalid use of nonstatic data member 'x' }} + static char a[sizeof(x)]; // expected-error {{invalid use of non-static data member 'x'}} static char b[sizeof(sx)]; // okay - static char c[sizeof(f)]; // expected-error {{ call to non-static member function without an object argument }} + static char c[sizeof(f)]; // expected-error {{call to non-static member function without an object argument}} }; }; diff --git a/test/CXX/class/class.static/class.static.data/p3.cpp b/test/CXX/class/class.static/class.static.data/p3.cpp index 007e416e6a492..117997ee28393 100644 --- a/test/CXX/class/class.static/class.static.data/p3.cpp +++ b/test/CXX/class/class.static/class.static.data/p3.cpp @@ -1,12 +1,12 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -struct NonLit { +struct NonLit { // expected-note 3{{no constexpr constructors}} NonLit(); }; struct S { static constexpr int a = 0; - static constexpr int b; // expected-error {{declaration of constexpr variable 'b' requires an initializer}} + static constexpr int b; // expected-error {{declaration of constexpr static data member 'b' requires an initializer}} static constexpr int c = 0; static const int d; @@ -24,3 +24,21 @@ constexpr int S::b = 0; const int S::c; constexpr int S::d = 0; constexpr int S::d2; + +template<typename T> +struct U { + static constexpr int a = 0; + static constexpr int b; // expected-error {{declaration of constexpr static data member 'b' requires an initializer}} + static constexpr NonLit h = NonLit(); // expected-error {{cannot have non-literal type 'const NonLit'}} + static constexpr T c = T(); // expected-error {{cannot have non-literal type}} + static const T d; +}; + +template<typename T> constexpr T U<T>::d = T(); // expected-error {{non-literal type 'const NonLit'}} + +U<int> u1; +U<NonLit> u2; // expected-note {{here}} + +static_assert(U<int>::a == 0, ""); + +constexpr int outofline = (U<NonLit>::d, 0); // expected-note {{here}} expected-warning {{unused}} diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp index 011185fb49e48..f344ae5b01fb4 100644 --- a/test/CXX/class/class.union/p1.cpp +++ b/test/CXX/class/class.union/p1.cpp @@ -19,6 +19,9 @@ class Ctor { class Ctor2 { Ctor2(); // expected-note 3 {{because type 'Ctor2' has a user-declared constructor}} }; +class CtorTmpl { + template<typename T> CtorTmpl(); // expected-note {{because type 'CtorTmpl' has a user-declared constructor}} +}; class CopyCtor { CopyCtor(CopyCtor &cc) { abort(); } // expected-note 4 {{because type 'CopyCtor' has a user-declared copy constructor}} @@ -38,6 +41,7 @@ union U1 { VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}} Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}} Ctor2 ctor2; // expected-error {{union member 'ctor2' has a non-trivial constructor}} + CtorTmpl ctortmpl; // expected-error {{union member 'ctortmpl' has a non-trivial constructor}} CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}} CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}} Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}} @@ -91,8 +95,9 @@ union U3 { }; union U4 { - static int i1; // expected-error {{static data member 'i1' not allowed in union}} + static int i1; // expected-warning {{static data member 'i1' in union is a C++11 extension}} }; +int U4::i1 = 10; union U5 { int& i1; // expected-error {{union member 'i1' has reference type 'int &'}} diff --git a/test/CXX/class/class.union/p2-0x.cpp b/test/CXX/class/class.union/p2-0x.cpp new file mode 100644 index 0000000000000..b5c410925cec7 --- /dev/null +++ b/test/CXX/class/class.union/p2-0x.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +// Unlike in C++98, C++11 allows unions to have static data members. + +union U1 { + static constexpr int k1 = 0; + static const int k2 = k1; + static int k3 = k2; // expected-error {{non-const static data member must be initialized out of line}} + static constexpr double k4 = k2; + static const double k5 = k4; // expected-warning {{GNU extension}} expected-note {{use 'constexpr'}} + int n[k1 + 3]; +}; + +constexpr int U1::k1; +constexpr int U1::k2; +int U1::k3; + +const double U1::k4; +const double U1::k5; + +template<typename T> +union U2 { + static const int k1; + static double k2; + T t; +}; +template<typename T> constexpr int U2<T>::k1 = sizeof(U2<T>); +template<typename T> double U2<T>::k2 = 5.3; + +static_assert(U2<int>::k1 == sizeof(int), ""); +static_assert(U2<char>::k1 == sizeof(char), ""); + +union U3 { + static const int k; + U3() : k(0) {} // expected-error {{does not name a non-static data member}} +}; + +struct S { + union { + static const int n; // expected-error {{static members cannot be declared in an anonymous union}} + int a; + int b; + }; +}; +static union { + static const int k; // expected-error {{static members cannot be declared in an anonymous union}} + int n; +}; diff --git a/test/CXX/class/p6-0x.cpp b/test/CXX/class/p6-0x.cpp index 3384af09c7884..f2cf48282112f 100644 --- a/test/CXX/class/p6-0x.cpp +++ b/test/CXX/class/p6-0x.cpp @@ -13,3 +13,18 @@ static_assert(!__is_trivial(NonTrivial2), "NonTrivial2 is trivial"); static_assert(!__is_trivial(NonTrivial3), "NonTrivial3 is trivial"); static_assert(!__is_trivial(NonTrivial4), "NonTrivial4 is trivial"); static_assert(!__is_trivial(NonTrivial5), "NonTrivial5 is trivial"); + +struct Trivial2 { + Trivial2() = default; + Trivial2(const Trivial2 &) = default; + Trivial2(Trivial2 &&) = default; + Trivial2 &operator=(const Trivial2 &) = default; + Trivial2 &operator=(Trivial2 &) = default; + ~Trivial2() = default; +}; + +class NonTrivial6 { ~NonTrivial6(); }; + +NonTrivial6::~NonTrivial6() = default; + +static_assert(!__is_trivial(NonTrivial6), "NonTrivial6 is trivial"); diff --git a/test/CXX/conv/conv.prom/p2.cpp b/test/CXX/conv/conv.prom/p2.cpp new file mode 100644 index 0000000000000..8d75419878ad4 --- /dev/null +++ b/test/CXX/conv/conv.prom/p2.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -ffreestanding %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -fshort-wchar -ffreestanding %s + +#include <stdint.h> + +// In theory, the promoted types vary by platform; however, in reality they +// are quite consistent across all platforms where clang runs. + +extern int promoted_wchar; +extern decltype(+L'a') promoted_wchar; + +extern int promoted_char16; +extern decltype(+u'a') promoted_char16; + +extern unsigned promoted_char32; +extern decltype(+U'a') promoted_char32; diff --git a/test/CXX/conv/conv.prom/p4.cpp b/test/CXX/conv/conv.prom/p4.cpp new file mode 100644 index 0000000000000..02a91cd521b4f --- /dev/null +++ b/test/CXX/conv/conv.prom/p4.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +enum X : short { A, B }; +extern decltype(+A) x; +extern int x; + +enum Y : long { C, D }; +extern decltype(+C) y; +extern long y; diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp index 634369dd52304..bf30ee74a5676 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp @@ -39,7 +39,7 @@ namespace Test0 { test<2> _1 = (foo)(a); class Test0::foo b; - test<2> _2 = (foo)(b); // expected-error {{no viable conversion from 'class Test0::foo' to 'class ::foo' is possible}} + test<2> _2 = (foo)(b); // expected-error {{no viable conversion from 'class Test0::foo' to 'class ::foo'}} } } } @@ -76,7 +76,7 @@ namespace test2 { class B : private A { protected: - using A::operator int; // expected-note {{'declared protected here'}} + using A::operator int; // expected-note {{declared protected here}} public: using A::operator bool; }; diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp index 63b302265ea0f..c7966ce643f1b 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp @@ -12,26 +12,26 @@ namespace test0 { namespace ns { void foo(); } // expected-note {{target of using declaration}} - int foo(); // expected-note {{conflicting declaration}} + int foo(void); // 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}} + int foo(void); // 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}} + int foo(void); // 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}} + int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} } } @@ -39,7 +39,7 @@ namespace test3 { namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} class Test0 { void test() { - int foo(); // expected-note {{conflicting declaration}} + int foo(void); // expected-note {{conflicting declaration}} using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} } }; @@ -47,7 +47,7 @@ namespace test3 { 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}} + int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} } }; } @@ -56,7 +56,7 @@ 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}} + int foo(void); // expected-note {{conflicting declaration}} using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} } }; @@ -64,16 +64,14 @@ namespace test4 { 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}} + int foo(void); // 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}} + namespace ns { void foo(int); } template <typename T> class Test0 { void test() { int foo(T); @@ -83,12 +81,11 @@ namespace test5 { 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}} + using ns::foo; + int foo(T); } }; template class Test0<int>; - template class Test1<int>; // expected-note {{in instantiation of member function}} + template class Test1<int>; } - diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp new file mode 100644 index 0000000000000..f9702ba7ccb02 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace std_example { + +int p[10]; +void f() { + int x = 42, y[5]; + // FIXME: Produce a better diagnostic for this case. + int(p[[x] { return x; }()]); // expected-error {{expected ']'}} + y[[] { return 2; }()] = 2; // expected-error {{consecutive left square brackets}} +} + +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index ed98c1e9c56d3..6820fc6cb8796 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -struct notlit { +struct notlit { // expected-note {{not literal because}} notlit() {} }; struct notlit2 { @@ -20,7 +20,7 @@ constexpr int s1::mi2 = 0; // not a definition of an object constexpr extern int i2; // expected-error {{constexpr variable declaration must be a definition}} // not a literal type -constexpr notlit nl1; // expected-error {{declaration of constexpr variable 'nl1' requires an initializer}} +constexpr notlit nl1; // expected-error {{constexpr variable cannot have non-literal type 'const notlit'}} // function parameters void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}} // non-static member @@ -35,6 +35,9 @@ constexpr class C1 {}; // expected-error {{class cannot be marked constexpr}} constexpr struct S1 {}; // expected-error {{struct cannot be marked constexpr}} constexpr union U1 {}; // expected-error {{union cannot be marked constexpr}} constexpr enum E1 {}; // expected-error {{enum cannot be marked constexpr}} +template <typename T> constexpr class TC1 {}; // expected-error {{class cannot be marked constexpr}} +template <typename T> constexpr struct TS1 {}; // expected-error {{struct cannot be marked constexpr}} +template <typename T> constexpr union TU1 {}; // expected-error {{union cannot be marked constexpr}} class C2 {} constexpr; // expected-error {{class cannot be marked constexpr}} struct S2 {} constexpr; // expected-error {{struct cannot be marked constexpr}} union U2 {} constexpr; // expected-error {{union cannot be marked constexpr}} @@ -72,21 +75,18 @@ struct S { }; // explicit specialization can differ in constepxr -// FIXME: When checking the explicit specialization, we implicitly instantiate -// the primary template then claim a constexpr mismatch. template <> notlit ft(notlit nl) { return nl; } -template <> char ft(char c) { return c; } // desired-note {{previous}} unexpected-error {{follows constexpr declaration}} unexpected-note {{here}} -template <> constexpr char ft(char nl); // desired-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}} -template <> constexpr int gt(int nl) { return nl; } // unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}} +template <> char ft(char c) { return c; } // expected-note {{previous}} +template <> constexpr char ft(char nl); // expected-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}} +template <> constexpr int gt(int nl) { return nl; } template <> notlit S::f() const { return notlit(); } -template <> constexpr int S::g() { return 0; } // desired-note {{previous}} unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}} -template <> int S::g() const; // desired-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}} +template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok -// FIXME: The initializer is a constant expression. -constexpr int i3 = ft(1); // unexpected-error {{must be initialized by a constant expression}} +constexpr int i3 = ft(1); void test() { // ignore constexpr when instantiating with non-literal @@ -95,7 +95,7 @@ void test() { } // Examples from the standard: -constexpr int square(int x); +constexpr int square(int x); // expected-note {{declared here}} constexpr int bufsz = 1024; constexpr struct pixel { // expected-error {{struct cannot be marked constexpr}} @@ -105,17 +105,16 @@ constexpr struct pixel { // expected-error {{struct cannot be marked constexpr}} }; constexpr pixel::pixel(int a) - : x(square(a)), y(square(a)) + : x(square(a)), y(square(a)) // expected-note {{undefined function 'square' cannot be used in a constant expression}} { } -constexpr pixel small(2); // expected-error {{must be initialized by a constant expression}} +constexpr pixel small(2); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'pixel(2)'}} constexpr int square(int x) { return x * x; } -// FIXME: The initializer is a constant expression. -constexpr pixel large(4); // unexpected-error {{must be initialized by a constant expression}} +constexpr pixel large(4); int next(constexpr int x) { // expected-error {{function parameter cannot be constexpr}} return x + 1; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 03406dbf918a4..cafdd635518c9 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -8,7 +8,7 @@ namespace M { typedef double D; } -struct NonLiteral { // expected-note 4{{no constexpr constructors}} +struct NonLiteral { // expected-note 2{{no constexpr constructors}} NonLiteral() {} NonLiteral(int) {} }; @@ -24,30 +24,28 @@ struct SS : S { int ImplicitlyVirtual() const; }; -// Note, the wording applies constraints to the definition of constexpr -// functions, but we intentionally apply all that we can to the declaration -// instead. See DR1360. - // The definition of a constexpr function shall satisfy the following // constraints: -struct T : SS { // expected-note {{base class 'SS' of non-literal type}} - constexpr T(); // expected-error {{non-literal type 'T' cannot have constexpr members}} +struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}} + constexpr T(); + constexpr int f(); // expected-error {{non-literal type 'T' cannot have constexpr members}} // - it shall not be virtual; - virtual constexpr int ExplicitlyVirtual(); // expected-error {{virtual function cannot be constexpr}} + virtual constexpr int ExplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}} - constexpr int ImplicitlyVirtual(); // expected-error {{virtual function cannot be constexpr}} + constexpr int ImplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}} // - its return type shall be a literal type; - constexpr NonLiteral NonLiteralReturn(); // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr NonLiteral NonLiteralReturn() { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr void VoidReturn() { return; } // expected-error {{constexpr function's return type 'void' is not a literal type}} constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}} typedef NonLiteral F(); - constexpr F NonLiteralReturn2; // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr F NonLiteralReturn2; // ok until definition // - each of its parameter types shall be a literal type; - constexpr int NonLiteralParam(NonLiteral); // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + constexpr int NonLiteralParam(NonLiteral) { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} typedef int G(NonLiteral); - constexpr G NonLiteralParam2; // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + constexpr G NonLiteralParam2; // ok until definition // - its function-body shall be = delete, = default, constexpr int Deleted() = delete; @@ -63,6 +61,10 @@ struct U { constexpr int SelfParam(U); }; +struct V : virtual U { // expected-note {{here}} + constexpr int F() { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}} +}; + // or a compound-statememt that contains only constexpr int AllowedStmts() { // - null statements @@ -123,3 +125,15 @@ constexpr int MultiReturn() { // return value shall be one of those allowed in a constant expression. // // We implement the proposed resolution of DR1364 and ignore this bullet. +// However, we implement the spirit of the check as part of the p5 checking that +// a constexpr function must be able to produce a constant expression. +namespace DR1364 { + constexpr int f(int k) { + return k; // ok, even though lvalue-to-rvalue conversion of a function + // parameter is not allowed in a constant expression. + } + int kGlobal; // expected-note {{here}} + constexpr int f() { // expected-error {{constexpr function never produces a constant expression}} + return kGlobal; // expected-note {{read of non-const}} + } +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index 9218bcf45bb47..65573c7533622 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -14,19 +14,16 @@ struct NonLiteral { // expected-note 2{{no constexpr constructors}} }; struct Literal { constexpr Literal() {} + explicit Literal(int); // expected-note 2 {{here}} operator int() const { return 0; } }; -// Note, the wording applies constraints to the definition of constexpr -// constructors, but we intentionally apply all that we can to the declaration -// instead. See DR1360. - // In the definition of a constexpr constructor, each of the parameter types // shall be a literal type. struct S { - constexpr S(int, N::C); - constexpr S(int, NonLiteral, N::C); // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} - constexpr S(int, NonLiteral = 42); // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + constexpr S(int, N::C) {} + constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} // In addition, either its function-body shall be = delete or = default constexpr S() = default; @@ -37,14 +34,14 @@ struct S { // - the class shall not have any virtual base classes; struct T : virtual S { // expected-note {{here}} - constexpr T(); // expected-error {{constexpr constructor not allowed in struct with virtual base classes}} + constexpr T() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} }; namespace IndirectVBase { struct A {}; struct B : virtual A {}; // expected-note {{here}} class C : public B { public: - constexpr C(); // expected-error {{constexpr constructor not allowed in class with virtual base classes}} + constexpr C() {} // expected-error {{constexpr constructor not allowed in class with virtual base class}} }; } @@ -150,6 +147,16 @@ struct AnonMembers { constexpr AnonMembers(int(&)[6]) {} // expected-error {{constexpr constructor must initialize all members}} }; +union Empty { + constexpr Empty() {} // ok +} constexpr empty1; + +struct EmptyVariant { + union {}; + struct {}; + constexpr EmptyVariant() {} // ok +} constexpr empty2; + template<typename T> using Int = int; template<typename T> struct TemplateInit { @@ -190,9 +197,17 @@ constexpr int f(enable_shared_from_this<int>); // - every constructor involved in initializing non-static data members and base // class sub-objects shall be a constexpr constructor. -// -// FIXME: Implement this as part of the 'must be able to produce a constant -// expression' rules. +struct ConstexprBaseMemberCtors : Literal { + Literal l; + + constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok + constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}} + Literal(0), // expected-note {{non-constexpr constructor}} + l() {} + constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}} + l(0) // expected-note {{non-constexpr constructor}} + {} +}; // - every assignment-expression that is an initializer-caluse appearing // directly or indirectly within a brace-or-equal-initializer for a non-static @@ -215,6 +230,14 @@ struct X { // expression. // // We implement the proposed resolution of DR1364 and ignore this bullet. +// However, we implement the intent of this wording as part of the p5 check that +// the function must be able to produce a constant expression. +int kGlobal; // expected-note {{here}} +struct Z { + constexpr Z(int a) : n(a) {} + constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} + int n; +}; namespace StdExample { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp new file mode 100644 index 0000000000000..fd17d35677dcc --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s + +namespace StdExample { + +constexpr int f(void *) { return 0; } +constexpr int f(...) { return 1; } +constexpr int g1() { return f(0); } +constexpr int g2(int n) { return f(n); } +constexpr int g3(int n) { return f(n*0); } + +namespace N { + constexpr int c = 5; + constexpr int h() { return c; } +} +constexpr int c = 0; +constexpr int g4() { return N::h(); } + +static_assert(f(0) == 0, ""); +static_assert(f('0') == 1, ""); +static_assert(g1() == 0, ""); +static_assert(g2(0) == 1, ""); +static_assert(g2(1) == 1, ""); +static_assert(g3(0) == 1, ""); +static_assert(g3(1) == 1, ""); +static_assert(N::h() == 5, ""); +static_assert(g4() == 5, ""); + + +constexpr int f(bool b) + { return b ? throw 0 : 0; } // ok +constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}} + +struct B { + constexpr B(int x) : i(0) { } + int i; +}; + +int global; // expected-note {{declared here}} + +struct D : B { + constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} +}; + +} + +namespace PotentialConstant { + +constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}} + (void)(n * 2), + throw 0, // expected-note {{subexpression}} + 0; +} + +int ng; // expected-note 6{{here}} +constexpr int BinaryOp1(int n) { return n + ng; } // expected-error {{never produces}} expected-note {{read}} +constexpr int BinaryOp2(int n) { return ng + n; } // expected-error {{never produces}} expected-note {{read}} + +double dg; // expected-note 2{{here}} +constexpr double BinaryOp1(double d) { return d + dg; } // expected-error {{never produces}} expected-note {{read}} +constexpr double BinaryOp2(double d) { return dg + d; } // expected-error {{never produces}} expected-note {{read}} + +constexpr int Add(int a, int b, int c) { return a + b + c; } +constexpr int FunctionArgs(int a) { return Add(a, ng, a); } // expected-error {{never produces}} expected-note {{read}} + +struct S { int a; int b; int c[2]; }; +constexpr S InitList(int a) { return { a, ng }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList1a(int a) { return S{ a, ng }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList2(int a) { return { a, a, { ng } }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList3(int a) { return a ? S{ a, a } : S{ a, ng }; }; // ok + +constexpr int LogicalAnd1(int n) { return n && (throw, 0); } // ok +constexpr int LogicalAnd2(int n) { return 1 && (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}} + +constexpr int LogicalOr1(int n) { return n || (throw, 0); } // ok +constexpr int LogicalOr2(int n) { return 0 || (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}} + +constexpr int Conditional1(bool b, int n) { return b ? n : ng; } // ok +constexpr int Conditional2(bool b, int n) { return b ? n * ng : n + ng; } // expected-error {{never produces}} expected-note {{both arms of conditional operator are unable to produce a constant expression}} + +// __builtin_constant_p ? : is magical, and is always a potential constant. +constexpr bool BcpCall(int n) { + return __builtin_constant_p((int*)n != &n) ? (int*)n != &n : (int*)n != &n; +} +static_assert(BcpCall(0), ""); + +// DR1311: A function template which can produce a constant expression, but +// for which a particular specialization cannot, is ok. +template<typename T> constexpr T cmin(T a, T b) { + return a < b ? a : b; +} +int n = cmin(3, 5); // ok + +struct X { + constexpr X() {} + bool operator<(X); // not constexpr +}; + +X x = cmin(X(), X()); // ok, not constexpr + +// Same with other temploids. +template<typename T> +struct Y { + constexpr Y() {} + constexpr int get() { return T(); } +}; +struct Z { operator int(); }; + +int y1 = Y<int>().get(); // ok +int y2 = Y<Z>().get(); // ok + +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp index e383bc09226c8..1a6dc9ecfb5d1 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -10,7 +10,7 @@ namespace M { struct NonLiteral { NonLiteral() {} - NonLiteral(int) {} + NonLiteral(int) {} // expected-note 2{{here}} operator int() const { return 0; } }; struct Literal { @@ -19,7 +19,7 @@ struct Literal { }; struct S { - virtual int ImplicitlyVirtual(); + virtual int ImplicitlyVirtual() const; }; struct T {}; @@ -27,48 +27,42 @@ template<typename T> struct ImplicitVirtualFromDependentBase : T { constexpr int ImplicitlyVirtual() { return 0; } }; -// FIXME: Can't test this until we have function invocation substitution -#if 0 -constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // desired-error {{not a constant expression}} +constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate virtual function call}} constexpr int b = ImplicitVirtualFromDependentBase<T>().ImplicitlyVirtual(); // ok -#endif +constexpr int c = ImplicitVirtualFromDependentBase<S>().ImplicitVirtualFromDependentBase<S>::ImplicitlyVirtual(); template<typename R> struct ConstexprMember { constexpr R F() { return 0; } }; -// FIXME: Can't test this until we have function invocation substitution -#if 0 -constexpr int c = ConstexprMember<int>().F(); // ok -constexpr int d = ConstexprMember<NonLiteral>().F(); // desired-error {{not a constant expression}} -#endif +constexpr int d = ConstexprMember<int>().F(); // ok +constexpr int e = ConstexprMember<NonLiteral>().F(); // expected-error {{constant expression}} -template<typename ...P> struct ConstexprCtor { // expected-note 2{{no constexpr constructors}} - constexpr ConstexprCtor(P...); // expected-note {{constructor template instantiation is not constexpr because 1st parameter type 'NonLiteral' is not a literal type}} \ - expected-note {{constructor template instantiation is not constexpr because 2nd parameter type 'NonLiteral' is not a literal type}} +template<typename ...P> struct ConstexprCtor { + constexpr ConstexprCtor(P...) {} }; -constexpr ConstexprCtor<> f1(); // ok -constexpr ConstexprCtor<int> f2(); // ok -constexpr ConstexprCtor<NonLiteral> f3(); // expected-error {{not a literal type}} -constexpr ConstexprCtor<int, NonLiteral> f4(); // expected-error {{not a literal type}} +constexpr ConstexprCtor<> f1() { return {}; } // ok +constexpr ConstexprCtor<int> f2() { return 0; } // ok +constexpr ConstexprCtor<NonLiteral> f3() { return { 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}} +constexpr ConstexprCtor<int, NonLiteral> f4() { return { 0, 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}} struct VirtBase : virtual S {}; // expected-note {{here}} namespace TemplateVBase { template<typename T> struct T1 : virtual Literal { // expected-note {{here}} - constexpr T1(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}} + constexpr T1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} }; - template<typename T> struct T2 : virtual T { // expected-note {{struct with virtual base class is not a literal type}} expected-note {{here}} + template<typename T> struct T2 : virtual T { // FIXME: This is ill-formed (no diagnostic required). // We should diagnose it now rather than waiting until instantiation. - constexpr T2(); // desired-error {{constexpr constructor not allowed in class with virtual base classes}} + constexpr T2() {} }; - constexpr T2<Literal> g2(); // expected-error {{not a literal type}} + constexpr T2<Literal> g2() { return {}; } template<typename T> class T3 : public T { // expected-note {{class with virtual base class is not a literal type}} public: constexpr T3() {} }; - constexpr T3<Literal> g3(); // ok - constexpr T3<VirtBase> g4(); // expected-error {{not a literal type}} + constexpr T3<Literal> g3() { return {}; } // ok + constexpr T3<VirtBase> g4() { return {}; } // expected-error {{not a literal type}} } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp index f7da24dfc20a5..c4935b34a062d 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp @@ -1,13 +1,17 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s struct S { - constexpr void f(); - constexpr void g() const; + constexpr int f(); + constexpr int g() const; + static constexpr int Sf(); }; void f(const S &s) { s.f(); s.g(); + + int (*f)() = &S::Sf; + int (S::*g)() const = &S::g; } namespace std_example { @@ -26,3 +30,9 @@ namespace std_example { { return x * 2 + 3 * y; } } + +// The constexpr specifier is allowed for static member functions of non-literal types. +class NonLiteralClass { + NonLiteralClass(bool); + static constexpr bool isDebugFlag(); +}; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp index 53d232d8a90ad..2412a145f866c 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp @@ -5,7 +5,7 @@ constexpr int a = 0; extern const int a; -int i; +int i; // expected-note 2{{here}} constexpr int *b = &i; extern int *const b; @@ -17,21 +17,21 @@ extern int (*const d)(int); // A variable declaration which uses the constexpr specifier shall have an // initializer and shall be initialized by a constant expression. -constexpr int ni1; // expected-error {{declaration of constexpr variable 'ni1' requires an initializer}} -constexpr struct C { C(); } ni2; // expected-error {{declaration of constexpr variable 'ni2' requires an initializer}} -constexpr double &ni3; // expected-error {{declaration of constexpr variable 'ni3' requires an initializer}} +constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}} +constexpr struct C { C(); } ni2; // expected-error {{cannot have non-literal type 'const struct C'}} expected-note 3{{has no constexpr constructors}} +constexpr double &ni3; // expected-error {{declaration of reference variable 'ni3' requires an initializer}} -constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} -constexpr C nc2 = C(); // expected-error {{constexpr variable 'nc2' must be initialized by a constant expression}} -int &f(); -constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} -constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} -constexpr C nc5((C())); // expected-error {{constexpr variable 'nc5' must be initialized by a constant expression}} -int &f(); -constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} +constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +constexpr C nc2 = C(); // expected-error {{cannot have non-literal type 'const C'}} +int &f(); // expected-note {{declared here}} +constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +constexpr C nc5((C())); // expected-error {{cannot have non-literal type 'const C'}} +int &f(); // expected-note {{here}} +constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}} struct pixel { int x, y; }; constexpr pixel ur = { 1294, 1024 }; // ok -constexpr pixel origin; // expected-error {{requires an initializer}} +constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' requires a user-provided default constructor}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp new file mode 100644 index 0000000000000..44cc5a7cfaa3a --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-compat %s + +// The auto or register specifiers can be applied only to names of objects +// declared in a block (6.3) or to function parameters (8.4). + +auto int ao; // expected-error {{illegal storage class on file-scoped variable}} +auto void af(); // expected-error {{illegal storage class on function}} + +register int ro; // expected-error {{illegal storage class on file-scoped variable}} +register void rf(); // expected-error {{illegal storage class on function}} + +struct S { + auto int ao; // expected-error {{storage class specified for a member declaration}} + auto void af(); // expected-error {{storage class specified for a member declaration}} + + register int ro; // expected-error {{storage class specified for a member declaration}} + register void rf(); // expected-error {{storage class specified for a member declaration}} +}; + +void foo(auto int ap, register int rp) { + auto int abo; + auto void abf(); // expected-error {{illegal storage class on function}} + + register int rbo; + register void rbf(); // expected-error {{illegal storage class on function}} +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp index 7b5577520d421..a385aa91329d0 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp @@ -44,6 +44,6 @@ struct F : auto(*)()->int {}; // expected-error{{expected class name}} template<typename T = auto(*)()->int> struct G { }; int g(); -auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}} +auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed in function return type}} auto (*i)() = &g; // ok; auto deduced as int. auto (*k)() -> int = i; // ok; no deduction. diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp index 682ee9f7e4ec9..1daf02f6ea51d 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions -Wc++11-compat void f() { auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}} auto *b = b; // expected-error{{variable 'b' declared with 'auto' type cannot appear in its own initializer}} @@ -13,9 +13,9 @@ void g() { auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}} - if (auto b) {} // expected-error {{expected '='}} - for (;auto b;) {} // expected-error {{expected '='}} - while (auto b) {} // expected-error {{expected '='}} + if (auto b) {} // expected-error {{must have an initializer}} + for (;auto b;) {} // expected-error {{must have an initializer}} + while (auto b) {} // expected-error {{must have an initializer}} if (auto b = true) { (void)b; } } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp index 095c031a1a0ed..e566d2a8f1d28 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions template<typename T> struct only { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index a52ef41504ac8..71f57dcc66e7b 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -60,9 +60,9 @@ int ints[] = {1, 2, 3}; template <const auto (*a)[3] = &ints> class D { }; // expected-error{{'auto' not allowed in template parameter}} enum E : auto {}; // expected-error{{'auto' not allowed here}} struct F : auto {}; // expected-error{{expected class name}} -template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}} +template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed in template argument}} using A = auto; // expected-error{{'auto' not allowed in type alias}} // FIXME: don't issue the second diagnostic for this error. -auto k() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}} +auto k() -> auto; // expected-error{{'auto' not allowed in function return type}} unexpected-error{{without trailing return type}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp index 7ed4daec5dec1..d327efcc20df5 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions template<typename T> struct only { @@ -92,7 +92,7 @@ namespace PR10939 { template<typename T> T g(T); void f(X *x) { - auto value = x->method; // expected-error{{variable 'value' with type 'auto' has incompatible initializer of type '<bound member function type>'}} + auto value = x->method; // expected-error {{reference to non-static member function must be called}} if (value) { } auto funcptr = &g<int>; @@ -100,4 +100,5 @@ namespace PR10939 { } } -// TODO: if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>. +// if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>: +// see SemaCXX/cxx0x-initializer-stdinitializerlist.cpp diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp index 4f230cfb8d40b..9c1d397a1fbc1 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions void f() { auto a = 0, b = 0, c = 0; auto d = 0, e = 0.0; // expected-error {{'int' in declaration of 'd' and deduced as 'double' in declaration of 'e'}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp index b04e869a4860b..8d58498802325 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -class A {}; // expected-note 3 {{previous use is here}} +class A {}; // expected-note 4 {{previous use is here}} +enum E {}; void a1(struct A); void a2(class A); @@ -12,8 +13,8 @@ class A1 { friend class A; friend union A; // expected-error {{use of 'A' with tag type that does not match previous declaration}} - friend enum A; // expected-error {{ISO C++ forbids forward references to 'enum' types}} \ - // expected-warning {{cannot be a friend}} + friend enum A; // expected-error {{use of 'A' with tag type that does not match previous declaration}} + friend enum E; // expected-warning {{cannot be a friend}} }; template <class T> struct B { // expected-note {{previous use is here}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp index bc60b5e55a335..53227ea37ce9e 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp @@ -19,3 +19,9 @@ static_assert(is_same<decltype(foo()), const int&&>::value, ""); static_assert(is_same<decltype(i), int>::value, ""); static_assert(is_same<decltype(a->x), double>::value, ""); static_assert(is_same<decltype((a->x)), const double&>::value, ""); +static_assert(is_same<decltype(static_cast<int&&>(i)), int&&>::value, ""); + +int f0(int); // expected-note{{possible target}} +float f0(float); // expected-note{{possible target}} + +decltype(f0) f0_a; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp new file mode 100644 index 0000000000000..2bd5d234ce7f2 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace std_example { + +template<class T> struct A { ~A() = delete; }; // expected-note {{deleted here}} +template<class T> auto h() -> A<T>; +template<class T> auto i(T) -> T; +template<class T> auto f(T) -> decltype(i(h<T>())); // #1 +template<class T> auto f(T) -> void; // #2 +auto g() -> void { + f(42); // ok, calls #2, since #1 is not viable. +} +template<class T> auto q(T) -> decltype((h<T>())); +void r() { + // Deduction against q succeeds, but results in a temporary which can't be + // destroyed. + q(42); // expected-error {{attempt to use a deleted function}} +} + +} + +class PD { + friend struct A; + ~PD(); // expected-note 4{{here}} +public: + typedef int n; +}; +struct DD { + ~DD() = delete; // expected-note 2{{here}} + typedef int n; +}; + +struct A { + decltype(PD()) s; // ok + decltype(PD())::n n; // ok + decltype(DD()) *p = new decltype(DD()); // ok +}; + +// Two errors here: one for the decltype, one for the variable. +decltype(PD(), PD()) pd1; // expected-error 2{{private destructor}} +decltype(DD(), DD()) dd1; // expected-error 2{{deleted function}} + +decltype(((13, ((DD())))))::n dd_parens; // ok +decltype(((((42)), PD())))::n pd_parens_comma; // ok + +// Ensure parens aren't stripped from a decltype node. +extern decltype(PD()) pd_ref; // ok +decltype((pd_ref)) pd_ref3 = pd_ref; // ok, PD & +decltype(pd_ref) pd_ref2 = pd_ref; // expected-error {{private destructor}} + +namespace libcxx_example { + struct nat { + nat() = delete; + nat(const nat&) = delete; + nat &operator=(const nat&) = delete; + ~nat() = delete; + }; + struct any { + any(...); + }; + + template<typename T, typename U> struct is_same { static const bool value = false; }; + template<typename T> struct is_same<T, T> { static const bool value = true; }; + + template<typename T> T declval(); + + void swap(int &a, int &b); + nat swap(any, any); + + template<typename T> struct swappable { + typedef decltype(swap(declval<T&>(), declval<T&>())) type; + static const bool value = !is_same<type, nat>::value; + constexpr operator bool() { return value; } + }; + + static_assert(swappable<int>(), ""); + static_assert(!swappable<const int>(), ""); +} + +namespace RequireCompleteType { + template<int N, bool OK> struct S { + static_assert(OK, "boom!"); // expected-error 2{{boom!}} + }; + + template<typename T> T make(); + template<int N, bool OK> S<N, OK> make(); + void consume(...); + + decltype(make<0, false>()) *p1; // ok + decltype((make<1, false>())) *p2; // ok + + // A complete type is required here in order to detect an overloaded 'operator,'. + decltype(123, make<2, false>()) *p3; // expected-note {{here}} + + decltype(consume(make<3, false>())) *p4; // expected-note {{here}} + + decltype(make<decltype(make<4, false>())>()) *p5; // ok +} + +namespace Overload { + DD operator+(PD &a, PD &b); + decltype(PD()) *pd_ptr; + decltype(*pd_ptr + *pd_ptr) *dd_ptr; // ok + + decltype(0, *pd_ptr) pd_ref2 = pd_ref; // ok + DD operator,(int a, PD b); + decltype(0, *pd_ptr) *dd_ptr2; // expected-error {{private destructor}} +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp index e32774a2ee0f5..0b518bb08573e 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -fcxx-exceptions using X = struct { // ok }; @@ -7,21 +7,21 @@ template<typename T> using Y = struct { // expected-error {{can not be defined i class K { virtual ~K(); - // FIXME: Diagnostic could use some work - operator struct S {} (); // expected-error{{ 'operator S' cannot be the name of a variable or data member}} \ - // expected-error{{expected ';' at end of declaration list}} + operator struct S {} (); // expected-error{{'K::S' can not be defined in a type specifier}} }; +struct A {}; + void f() { int arr[3] = {1,2,3}; for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}} } - new struct T {}; // expected-error {{allocation of incomplete type}} expected-note {{forward declaration}} + new struct T {}; // expected-error {{'T' can not be defined in a type specifier}} + new struct A {}; // expected-error {{'A' can not be defined in a type specifier}} - // FIXME: the diagnostic here isn't very good - try {} catch (struct U {}); // expected-error 3{{}} expected-note 2{{}} + try {} catch (struct U {}) {} // expected-error {{'U' can not be defined in a type specifier}} (void)(struct V { V(int); })0; // expected-error {{'V' can not be defined in a type specifier}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp index 0ff40bccef9f0..b06eb01a7fb5c 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp @@ -15,12 +15,12 @@ namespace IllegalTypeIds { using C = virtual void(int n); // expected-error {{type name does not allow function specifier}} using D = explicit void(int n); // expected-error {{type name does not allow function specifier}} using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}} - // FIXME: this is illegal; we incorrectly accept it for typedefs too. - using F = void(*)(int n) &&; // expected-err + using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}} using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}} + using H = constexpr int; // expected-error {{type name does not allow constexpr specifier}} - using H = void(int n); // ok - using I = void(int n) &&; // ok + using Y = void(int n); // ok + using Z = void(int n) &&; // ok } namespace IllegalSyntax { @@ -124,9 +124,8 @@ namespace TagName { } namespace CWG1044 { - // FIXME: this is terrible. one error is plenty. + // FIXME: this diagnostic isn't ideal. one diagnostic is enough. using T = T; // expected-error {{type name requires a specifier}} \ - expected-error {{C++ requires a type specifier}} \ expected-error {{expected ';' after alias declaration}} } diff --git a/test/CXX/dcl.dcl/p4-0x.cpp b/test/CXX/dcl.dcl/p4-0x.cpp new file mode 100644 index 0000000000000..31d49127e7a77 --- /dev/null +++ b/test/CXX/dcl.dcl/p4-0x.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only %s + +struct S { + constexpr S(bool b) : b(b) {} + constexpr explicit operator bool() { return b; } + bool b; +}; +struct T { + constexpr operator int() { return 1; } +}; +struct U { + constexpr operator int() { return 1; } // expected-note {{candidate}} + constexpr operator long() { return 0; } // expected-note {{candidate}} +}; + +static_assert(S(true), ""); +static_assert(S(false), "not so fast"); // expected-error {{not so fast}} +static_assert(T(), ""); +static_assert(U(), ""); // expected-error {{ambiguous}} + +static_assert(false, L"\x14hi" "!" R"x(")x"); // expected-error {{static_assert failed L"\024hi!\""}} diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp new file mode 100644 index 0000000000000..06dd1bb05560b --- /dev/null +++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// An explicitly-defaulted function may be declared constexpr only if it would +// have been implicitly declared as constexpr. +struct S1 { + constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}} + constexpr S1(const S1&) = default; + constexpr S1(S1&&) = default; + constexpr S1 &operator=(const S1&) = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}} + constexpr S1 &operator=(S1&&) = default; // expected-error {{explicitly-defaulted move assignment operator may not have}} + constexpr ~S1() = default; // expected-error {{destructor cannot be marked constexpr}} + int n; +}; +struct NoCopyMove { + constexpr NoCopyMove() {} + NoCopyMove(const NoCopyMove&); + NoCopyMove(NoCopyMove&&); +}; +struct S2 { + constexpr S2() = default; + constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}} + constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}} + NoCopyMove ncm; +}; + +// If a function is explicitly defaulted on its first declaration +// -- it is implicitly considered to be constexpr if the implicit declaration +// would be +struct S3 { + S3() = default; // expected-note {{here}} + S3(const S3&) = default; + S3(S3&&) = default; + constexpr S3(int n) : n(n) {} + int n; +}; +constexpr S3 s3a = S3(0); +constexpr S3 s3b = s3a; +constexpr S3 s3c = S3(); +constexpr S3 s3d; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct S4 { + S4() = default; + S4(const S4&) = default; // expected-note {{here}} + S4(S4&&) = default; // expected-note {{here}} + NoCopyMove ncm; +}; +constexpr S4 s4a; // ok +constexpr S4 s4b = S4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} +constexpr S4 s4c = s4a; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct S5 { + constexpr S5(); + int n = 1, m = n + 3; +}; +constexpr S5::S5() = default; +static_assert(S5().m == 4, ""); diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp index b8c1e18a2e135..7764980e34f7e 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp @@ -8,55 +8,71 @@ private: protected: struct Inner { int m; }; public: - bool &br; + bool &br; // expected-note {{default constructor of 'Aggr' is implicitly deleted because field 'br' of reference type 'bool &' would not be initialized}} }; bool b; Aggr ag = { b }; // with no user-provided constructors, ... -struct NonAggr1a { - NonAggr1a(int, int); +struct NonAggr1a { // expected-note 2 {{candidate constructor}} + NonAggr1a(int, int); // expected-note {{candidate constructor}} int k; }; // In C++0x, 'user-provided' is only defined for special member functions, so // this type is considered to be an aggregate. This is considered to be // a language defect. -NonAggr1a na1a = { 42 }; // expected-error {{non-aggregate type 'NonAggr1a'}} +NonAggr1a na1a = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr1a'}} struct NonAggr1b { - NonAggr1b(const NonAggr1b &); + NonAggr1b(const NonAggr1b &); // expected-note {{candidate constructor}} int k; }; -NonAggr1b na1b = { 42 }; // expected-error {{non-aggregate type 'NonAggr1b'}} +NonAggr1b na1b = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr1b'}} // no brace-or-equal-initializers for non-static data members, ... -struct NonAggr2 { +struct NonAggr2 { // expected-note 3 {{candidate constructor}} int m = { 123 }; }; -NonAggr2 na2 = { 42 }; // expected-error {{non-aggregate type 'NonAggr2'}} +NonAggr2 na2 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr2'}} // no private... -struct NonAggr3 { +struct NonAggr3 { // expected-note 3 {{candidate constructor}} private: int n; }; -NonAggr3 na3 = { 42 }; // expected-error {{non-aggregate type 'NonAggr3'}} +NonAggr3 na3 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr3'}} // or protected non-static data members, ... -struct NonAggr4 { +struct NonAggr4 { // expected-note 3 {{candidate constructor}} protected: int n; }; -NonAggr4 na4 = { 42 }; // expected-error {{non-aggregate type 'NonAggr4'}} +NonAggr4 na4 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr4'}} // no base classes, ... -struct NonAggr5 : Aggr { +struct NonAggr5 : Aggr { // expected-note 3 {{candidate constructor}} }; -NonAggr5 na5 = { b }; // expected-error {{non-aggregate type 'NonAggr5'}} +NonAggr5 na5 = { b }; // expected-error {{no matching constructor for initialization of 'NonAggr5'}} +template<typename...BaseList> +struct MaybeAggr5a : BaseList... {}; // expected-note {{default constructor of 'MaybeAggr5a<Aggr>' is implicitly deleted because base class 'Aggr' has a deleted default constructor}} +MaybeAggr5a<> ma5a0 = {}; // ok +MaybeAggr5a<Aggr> ma5a1 = {}; // expected-error {{call to implicitly-deleted default constructor of 'MaybeAggr5a<Aggr>'}} // and no virtual functions. -struct NonAggr6 { +struct NonAggr6 { // expected-note 3 {{candidate constructor}} virtual void f(); int n; }; -NonAggr6 na6 = { 42 }; // expected-error {{non-aggregate type 'NonAggr6'}} +NonAggr6 na6 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr6'}} + +struct DefaultedAggr { + int n; + + DefaultedAggr() = default; + DefaultedAggr(const DefaultedAggr &) = default; + DefaultedAggr(DefaultedAggr &&) = default; + DefaultedAggr &operator=(const DefaultedAggr &) = default; + DefaultedAggr &operator=(DefaultedAggr &) = default; + ~DefaultedAggr() = default; +}; +DefaultedAggr da = { 42 } ; 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 index 5ebc22fd82074..b30e0ec7856ba 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp @@ -1,5 +1,17 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s void f0() { int &ir = { 17 }; // expected-error{{reference to type 'int' cannot bind to an initializer list}} } + +namespace PR12453 { + template<typename T> + void f(int i) { + T x{i}; // expected-error{{non-constant-expression cannot be narrowed from type 'int' to 'float' in initializer list}} \ + // expected-note{{override this message by inserting an explicit cast}} + T y{i}; // expected-error{{non-constant-expression cannot be narrowed from type 'int' to 'float' in initializer list}} \ + // expected-note{{override this message by inserting an explicit cast}} + } + + template void f<float>(int); // expected-note{{in instantiation of function template specialization 'PR12453::f<float>' requested here}} +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp index dc49deabdea4d..0bea4ede19cad 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wc++0x-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s // Verify that the appropriate fixits are emitted for narrowing conversions in // initializer lists. diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp index 2294a4eb08940..db20ea6426e00 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp @@ -31,12 +31,20 @@ struct Agg { T t; }; +template<typename T> +struct Convert { + constexpr Convert(T v) : v(v) {} + constexpr operator T() const { return v; } + T v; +}; +template<typename T> Convert<T> ConvertVar(); + // C++0x [dcl.init.list]p7: A narrowing conversion is an implicit conversion // // * from a floating-point type to an integer type, or void float_to_int() { - Agg<char> a1 = {1.0F}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a1 = {1.0F}; // expected-error {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} Agg<char> a2 = {1.0}; // expected-error {{ cannot be narrowed }} expected-note {{override}} Agg<char> a3 = {1.0L}; // expected-error {{ cannot be narrowed }} expected-note {{override}} @@ -46,6 +54,9 @@ void float_to_int() { Agg<char> a4 = {f}; // expected-error {{ cannot be narrowed }} expected-note {{override}} Agg<char> a5 = {d}; // expected-error {{ cannot be narrowed }} expected-note {{override}} Agg<char> a6 = {ld}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + Agg<char> ce1 = { Convert<float>(1.0) }; // expected-error {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> ce2 = { ConvertVar<double>() }; // expected-error {{type 'double' cannot be narrowed to 'char'}} expected-note {{override}} } // * from long double to double or float, or from double to float, except where @@ -61,7 +72,7 @@ void shrink_float() { // Variables. Agg<float> f1 = {f}; // OK (no-op) - Agg<float> f2 = {d}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<float> f2 = {d}; // expected-error {{non-constant-expression cannot be narrowed from type 'double' to 'float'}} expected-note {{override}} Agg<float> f3 = {ld}; // expected-error {{ cannot be narrowed }} expected-note {{override}} // Exact constants. Agg<float> f4 = {1.0}; // OK (double constant represented exactly) @@ -70,7 +81,7 @@ void shrink_float() { Agg<float> f6 = {0.1}; // OK (double constant in range but rounded) Agg<float> f7 = {0.1L}; // OK (long double constant in range but rounded) // Out of range constants. - Agg<float> f8 = {1E50}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<float> f8 = {1E50}; // expected-error {{constant expression evaluates to 1.000000e+50 which cannot be narrowed to type 'float'}} expected-note {{override}} Agg<float> f9 = {1E50L}; // expected-error {{ cannot be narrowed }} expected-note {{override}} // More complex constant expression. constexpr long double e40 = 1E40L, e30 = 1E30L, e39 = 1E39L; @@ -89,6 +100,9 @@ void shrink_float() { // More complex constant expression. constexpr long double e315 = 1E315L, e305 = 1E305L, e314 = 1E314L; Agg<double> d7 = {e315 - 5 * e314 + e305 - 5 * e314}; // OK + + Agg<float> ce1 = { Convert<double>(1e300) }; // expected-error {{constant expression evaluates to 1.000000e+300 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long double>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'long double' to 'double'}} expected-note {{override}} } // * from an integer type or unscoped enumeration type to a floating-point type, @@ -107,6 +121,9 @@ void int_to_float() { // Constants. Agg<float> f4 = {12345678}; // OK (exactly fits in a float) Agg<float> f5 = {123456789}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + Agg<float> ce1 = { Convert<int>(123456789) }; // expected-error {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long long>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{override}} } // * from an integer type or unscoped enumeration type to an integer type that @@ -147,6 +164,9 @@ void shrink_int() { // Conversions from pointers to booleans aren't narrowing conversions. Agg<bool> b = {&b1}; // OK + + Agg<short> ce1 = { Convert<int>(100000) }; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{override}} expected-warning {{changes value from 100000 to -31072}} + Agg<char> ce2 = { ConvertVar<short>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{override}} } // Be sure that type- and value-dependent expressions in templates get the error @@ -173,3 +193,17 @@ void test_qualifiers(int i) { // Template arguments make it harder to avoid printing qualifiers: Agg<const unsigned char> c2 = {j}; // expected-error {{from type 'int' to 'const unsigned char' in}} expected-note {{override}} } + +// Test SFINAE checks. +template<unsigned> struct Value { }; + +template<typename T> +int &check_narrowed(Value<sizeof((T){1.1})>); + +template<typename T> +float &check_narrowed(...); + +void test_narrowed(Value<sizeof(int)> vi, Value<sizeof(double)> vd) { + int &ir = check_narrowed<double>(vd); + float &fr = check_narrowed<int>(vi); +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp new file mode 100644 index 0000000000000..4bcf113d71429 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-error=c++11-narrowing -triple x86_64-apple-macosx10.6.7 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-error=narrowing -triple x86_64-apple-macosx10.6.7 -verify %s + +// Verify that narrowing conversions in initializer lists cause errors in C++0x +// mode. + +void std_example() { + int x = 999; // x is not a constant expression + const int y = 999; + const int z = 99; + char c1 = x; // OK, though it might narrow (in this case, it does narrow) + char c2{x}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + char c3{y}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + char c4{z}; // OK: no narrowing needed + unsigned char uc1 = {5}; // OK: no narrowing needed + unsigned char uc2 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + unsigned int ui1 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + signed int si1 = + { (unsigned int)-1 }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + int ii = {2.0}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + float f1 { x }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + float f2 { 7 }; // OK: 7 can be exactly represented as a float + int f(int); + int a[] = + { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level +} + +// Test each rule individually. + +template<typename T> +struct Agg { + T t; +}; + +template<typename T> +struct Convert { + constexpr Convert(T v) : v(v) {} + constexpr operator T() const { return v; } + T v; +}; +template<typename T> Convert<T> ConvertVar(); + +// C++0x [dcl.init.list]p7: A narrowing conversion is an implicit conversion +// +// * from a floating-point type to an integer type, or + +void float_to_int() { + Agg<char> a1 = {1.0F}; // expected-warning {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> a2 = {1.0}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a3 = {1.0L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + float f = 1.0; + double d = 1.0; + long double ld = 1.0; + Agg<char> a4 = {f}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a5 = {d}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a6 = {ld}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + Agg<char> ce1 = { Convert<float>(1.0) }; // expected-warning {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> ce2 = { ConvertVar<double>() }; // expected-warning {{type 'double' cannot be narrowed to 'char'}} expected-note {{override}} +} + +// * from long double to double or float, or from double to float, except where +// the source is a constant expression and the actual value after conversion +// is within the range of values that can be represented (even if it cannot be +// represented exactly), or + +void shrink_float() { + // These aren't constant expressions. + float f = 1.0; + double d = 1.0; + long double ld = 1.0; + + // Variables. + Agg<float> f1 = {f}; // OK (no-op) + Agg<float> f2 = {d}; // expected-warning {{non-constant-expression cannot be narrowed from type 'double' to 'float'}} expected-note {{override}} + Agg<float> f3 = {ld}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // Exact constants. + Agg<float> f4 = {1.0}; // OK (double constant represented exactly) + Agg<float> f5 = {1.0L}; // OK (long double constant represented exactly) + // Inexact but in-range constants. + Agg<float> f6 = {0.1}; // OK (double constant in range but rounded) + Agg<float> f7 = {0.1L}; // OK (long double constant in range but rounded) + // Out of range constants. + Agg<float> f8 = {1E50}; // expected-warning {{constant expression evaluates to 1.000000e+50 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<float> f9 = {1E50L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // More complex constant expression. + constexpr long double e40 = 1E40L, e30 = 1E30L, e39 = 1E39L; + Agg<float> f10 = {e40 - 5 * e39 + e30 - 5 * e39}; // OK + + // Variables. + Agg<double> d1 = {f}; // OK (widening) + Agg<double> d2 = {d}; // OK (no-op) + Agg<double> d3 = {ld}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // Exact constant. + Agg<double> d4 = {1.0L}; // OK (long double constant represented exactly) + // Inexact but in-range constant. + Agg<double> d5 = {0.1L}; // OK (long double constant in range but rounded) + // Out of range constant. + Agg<double> d6 = {1E315L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // More complex constant expression. + constexpr long double e315 = 1E315L, e305 = 1E305L, e314 = 1E314L; + Agg<double> d7 = {e315 - 5 * e314 + e305 - 5 * e314}; // OK + + Agg<float> ce1 = { Convert<double>(1e300) }; // expected-warning {{constant expression evaluates to 1.000000e+300 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long double>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'long double' to 'double'}} expected-note {{override}} +} + +// * from an integer type or unscoped enumeration type to a floating-point type, +// except where the source is a constant expression and the actual value after +// conversion will fit into the target type and will produce the original +// value when converted back to the original type, or +void int_to_float() { + // Not a constant expression. + char c = 1; + + // Variables. Yes, even though all char's will fit into any floating type. + Agg<float> f1 = {c}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<double> f2 = {c}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<long double> f3 = {c}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // Constants. + Agg<float> f4 = {12345678}; // OK (exactly fits in a float) + Agg<float> f5 = {123456789}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + Agg<float> ce1 = { Convert<int>(123456789) }; // expected-warning {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long long>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{override}} +} + +// * from an integer type or unscoped enumeration type to an integer type that +// cannot represent all the values of the original type, except where the +// source is a constant expression and the actual value after conversion will +// fit into the target type and will produce the original value when converted +// back to the original type. +void shrink_int() { + // Not a constant expression. + short s = 1; + unsigned short us = 1; + Agg<char> c1 = {s}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<unsigned short> s1 = {s}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<short> s2 = {us}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // "that cannot represent all the values of the original type" means that the + // validity of the program depends on the relative sizes of integral types. + // This test compiles with -m64, so sizeof(int)<sizeof(long)==sizeof(long + // long). + long l1 = 1; + Agg<int> i1 = {l1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + long long ll = 1; + Agg<long> l2 = {ll}; // OK + + // Constants. + Agg<char> c2 = {127}; // OK + Agg<char> c3 = {300}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + + Agg<int> i2 = {0x7FFFFFFFU}; // OK + Agg<int> i3 = {0x80000000U}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<unsigned int> i4 = {-0x80000000L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // Bool is also an integer type, but conversions to it are a different AST + // node. + Agg<bool> b1 = {0}; // OK + Agg<bool> b2 = {1}; // OK + Agg<bool> b3 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // Conversions from pointers to booleans aren't narrowing conversions. + Agg<bool> b = {&b1}; // OK + + Agg<short> ce1 = { Convert<int>(100000) }; // expected-warning {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{override}} expected-warning {{changes value from 100000 to -31072}} + Agg<char> ce2 = { ConvertVar<short>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{override}} +} + +// Be sure that type- and value-dependent expressions in templates get the warning +// too. + +template<int I, typename T> +void maybe_shrink_int(T t) { + Agg<short> s1 = {t}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<short> s2 = {I}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + Agg<T> t2 = {700}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} +} + +void test_template() { + maybe_shrink_int<15>((int)3); // expected-note {{in instantiation}} + maybe_shrink_int<70000>((char)3); // expected-note {{in instantiation}} +} + + +// We don't want qualifiers on the types in the diagnostic. + +void test_qualifiers(int i) { + const int j = i; + struct {const unsigned char c;} c1 = {j}; // expected-warning {{from type 'int' to 'unsigned char' in}} expected-note {{override}} + // Template arguments make it harder to avoid printing qualifiers: + Agg<const unsigned char> c2 = {j}; // expected-warning {{from type 'int' to 'const unsigned char' in}} expected-note {{override}} +} + +// Make sure we still get the right SFINAE behavior. +template<unsigned> struct Value { }; + +template<typename T> +int &check_narrowed(Value<sizeof((T){1.1})>); + +template<typename T> +float &check_narrowed(...); + +void test_narrowed(Value<sizeof(int)> vi, Value<sizeof(double)> vd) { + int &ir = check_narrowed<double>(vd); + float &fr = check_narrowed<int>(vi); +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp index 95cc56cbab536..adbdff6efe3c6 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s -// Test the C++0x-specific reference initialization rules, e.g., the +// Test the c++0x-specific reference initialization rules, e.g., the // rules for rvalue references. template<typename T> T prvalue(); template<typename T> T&& xvalue(); diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp index 8c654110fa24d..d58a12953e0d0 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -30,7 +30,7 @@ template<typename T> T get_value_badly() { double *dp = 0; // The extension doesn't extend far enough to turn this error into a warning. - T *tp = dp; // expected-error{{ cannot initialize a variable of type 'int *' with an lvalue of type 'double *'}} + T *tp = dp; // expected-error{{cannot initialize a variable of type 'int *' with an lvalue of type 'double *'}} return T(); } @@ -54,7 +54,7 @@ void g5(const X5&); void test() { g1(X1()); - g2(X2()); // expected-warning{{C++98 requires an accessible copy constructor for class 'X2' when binding a reference to a temporary; was private [-Wbind-to-temporary-copy]}} + g2(X2()); // expected-warning{{C++98 requires an accessible copy constructor for class 'X2' when binding a reference to a temporary; was private}} g3(X3()); // expected-warning{{no viable constructor copying parameter of type 'X3'}} g4(X4<int>()); g5(X5()); // Generates a warning in the default argument. diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp index 07a5cef304782..3631af1b7fd2f 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp @@ -5,3 +5,15 @@ extern char x1[6]; char x2[] = "hello"; extern char x2[6]; + +char x3[] = { "hello" }; +extern char x3[6]; + +wchar_t x4[](L"hello"); +extern wchar_t x4[6]; + +wchar_t x5[] = L"hello"; +extern wchar_t x5[6]; + +wchar_t x6[] = { L"hello" }; +extern wchar_t x6[6]; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp index ce0a082462a21..2ec1454100b69 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp @@ -1,20 +1,45 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -void f0() &; // expected-error{{ref-qualifier '&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} -void f1() &&; // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} +void f0() &; // expected-error {{non-member function cannot have '&' qualifier}} +void f1() &&; // expected-error {{non-member function cannot have '&&' qualifier}} +void f2() const volatile &&; // expected-error {{non-member function cannot have 'const volatile &&' qualifier}} struct X { - void f0() &; + void f0() &; void f1() &&; - static void f2() &; // expected-error{{ref-qualifier '&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} - static void f3() &&; // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} + static void f2() &; // expected-error{{static member function cannot have '&' qualifier}} + static void f3() &&; // expected-error{{static member function cannot have '&&' qualifier}} }; typedef void func_type_lvalue() &; typedef void func_type_rvalue() &&; -func_type_lvalue f2; // expected-error{{nonmember function cannot have a ref-qualifier '&'}} -func_type_rvalue f3; // expected-error{{nonmember function cannot have a ref-qualifier '&&'}} +typedef func_type_lvalue *func_type_lvalue_ptr; // expected-error{{pointer to function type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}} +typedef func_type_rvalue *func_type_rvalue_ptr; // expected-error{{pointer to function type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}} + +typedef func_type_lvalue &func_type_lvalue_ref; // expected-error{{reference to function type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}} +typedef func_type_rvalue &func_type_rvalue_ref; // expected-error{{reference to function type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}} + +template<typename T = func_type_lvalue> struct wrap { + typedef T val; + typedef T *ptr; + typedef T &ref; +}; + +using func_type_lvalue = wrap<>::val; +using func_type_lvalue = wrap<func_type_lvalue>::val; +using func_type_rvalue = wrap<func_type_rvalue>::val; + +using func_type_lvalue_ptr = wrap<>::ptr; +using func_type_lvalue_ptr = wrap<func_type_lvalue>::ptr; +using func_type_rvalue_ptr = wrap<func_type_rvalue>::ptr; + +using func_type_lvalue_ref = wrap<>::ref; +using func_type_lvalue_ref = wrap<func_type_lvalue>::ref; +using func_type_rvalue_ref = wrap<func_type_rvalue>::ref; + +func_type_lvalue f2; // expected-error{{non-member function of type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}} +func_type_rvalue f3; // expected-error{{non-member function of type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}} struct Y { func_type_lvalue f0; @@ -25,4 +50,4 @@ void (X::*mpf1)() & = &X::f0; void (X::*mpf2)() && = &X::f1; -void (f() &&); // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} +void (f() &&); // expected-error{{non-member function cannot have '&&' qualifier}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp index 4873c095a0ebf..e2d94fbf3811a 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp @@ -1,14 +1,20 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -void f() const; // expected-error{{type qualifier is not allowed on this function}} +typedef void F() const; + +void f() const; // expected-error {{non-member function cannot have 'const' qualifier}} +F g; // expected-error {{non-member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}} struct X { void f() const; - friend void g() const; // expected-error{{type qualifier is not allowed on this function}} - static void h() const; // expected-error{{type qualifier is not allowed on this function}} + friend void g() const; // expected-error {{non-member function cannot have 'const' qualifier}} + static void h() const; // expected-error {{static member function cannot have 'const' qualifier}} + F i; // ok + friend F j; // expected-error {{non-member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}} + static F k; // expected-error {{static member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}} }; struct Y { friend void X::f() const; - friend void ::f() const; // expected-error{{type qualifier is not allowed on this function}} + friend void ::f() const; // expected-error {{non-member function cannot have 'const' qualifier}} }; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp index 4d71a8e4b4c63..574a3e7a79341 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp @@ -1,3 +1,3 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -auto j() -> enum { e3 }; // expected-error{{can not be defined in a type specifier}} +auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{requires a specifier or qualifier}} expected-error {{without trailing return type}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp index aaf7451424019..c02105ca76cfa 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp @@ -12,7 +12,7 @@ typedef intref &intrefref; template <class T> class RefMem { // expected-warning{{class 'RefMem<int &>' does not declare any constructor to initialize its non-modifiable members}} T & - member; // expected-note{{ reference member 'member' will never be initialized}} + member; // expected-note{{reference member 'member' will never be initialized}} }; struct RefRef { diff --git a/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp new file mode 100644 index 0000000000000..99334b845aba2 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// The nested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier. +class foo { + static int i; + void func(); +}; + +int decltype(foo())::i; // expected-error{{'decltype' cannot be used to name a declaration}} +void decltype(foo())::func() { // expected-error{{'decltype' cannot be used to name a declaration}} +} + + +template<typename T> +class tfoo { + static int i; + void func(); +}; + +template<typename T> +int decltype(tfoo<T>())::i; // expected-error{{nested name specifier 'decltype(tfoo<T>())::' for declaration does not refer into a class, class template or class template partial specialization}} +template<typename T> +void decltype(tfoo<T>())::func() { // expected-error{{nested name specifier 'decltype(tfoo<T>())::' for declaration does not refer into a class, class template or class template partial specialization}} +} diff --git a/test/CXX/dcl.decl/dcl.meaning/p1.cpp b/test/CXX/dcl.decl/dcl.meaning/p1.cpp new file mode 100644 index 0000000000000..3672ea0ea086a --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/p1.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8019 { + struct x; + template<typename T> struct x2; + struct y { + struct PR8019::x { int x; }; // expected-error{{non-friend class member 'x' cannot have a qualified name}} + + struct inner; + struct y::inner { }; // expected-warning{{extra qualification on member 'inner'}} + + template<typename T> + struct PR8019::x2 { }; // expected-error{{non-friend class member 'x2' cannot have a qualified name}} + + template<typename T> + struct inner_template; + + template<typename T> + struct y::inner_template { }; // expected-warning{{extra qualification on member 'inner_template'}} + }; + +} + +namespace NS { + void foo(); + extern int bar; + struct X; + template<typename T> struct Y; + template<typename T> void wibble(T); +} +namespace NS { + void NS::foo() {} // expected-warning{{extra qualification on member 'foo'}} + int NS::bar; // expected-warning{{extra qualification on member 'bar'}} + struct NS::X { }; // expected-warning{{extra qualification on member 'X'}} + template<typename T> struct NS::Y; // expected-warning{{extra qualification on member 'Y'}} + template<typename T> void NS::wibble(T) { } // expected-warning{{extra qualification on member 'wibble'}} +} diff --git a/test/CXX/dcl.decl/dcl.name/p1.cpp b/test/CXX/dcl.decl/dcl.name/p1.cpp index 7586007cc7b38..9838b4f4737db 100644 --- a/test/CXX/dcl.decl/dcl.name/p1.cpp +++ b/test/CXX/dcl.decl/dcl.name/p1.cpp @@ -2,15 +2,19 @@ namespace pr6200 { struct v {}; + enum E { e }; struct s { int i; operator struct v() { return v(); }; + operator enum E() { return e; } }; void f() { - // Neither of these is a declaration. + // None of these is a declaration. (void)new struct s; + (void)new enum E; (void)&s::operator struct v; + (void)&s::operator enum E; } } diff --git a/test/CXX/except/except.spec/p1.cpp b/test/CXX/except/except.spec/p1.cpp index a6e7850247788..c68ec56a24912 100644 --- a/test/CXX/except/except.spec/p1.cpp +++ b/test/CXX/except/except.spec/p1.cpp @@ -74,7 +74,7 @@ namespace noexcept_unevaluated { namespace PR11084 { template<int X> struct A { - static int f() noexcept(1/X) { return 10; } // expected-error{{argument to noexcept specifier must be a constant expression}} + static int f() noexcept(1/X) { return 10; } // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}} }; void g() { A<0>::f(); } // expected-note{{in instantiation of template class 'PR11084::A<0>' requested here}} diff --git a/test/CXX/expr/expr.ass/p9-cxx11.cpp b/test/CXX/expr/expr.ass/p9-cxx11.cpp new file mode 100644 index 0000000000000..206c82c985c74 --- /dev/null +++ b/test/CXX/expr/expr.ass/p9-cxx11.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +template<typename T> struct complex { + complex(T = T(), T = T()); + void operator+=(complex); + T a, b; +}; + +void std_example() { + complex<double> z; + z = { 1, 2 }; + z += { 1, 2 }; + + int a, b; + a = b = { 1 }; + a = { 1 } = b; // expected-error {{initializer list cannot be used on the left hand side of operator '='}} + a = a + { 4 }; // expected-error {{initializer list cannot be used on the right hand side of operator '+'}} + a = { 3 } * { 4 }; // expected-error {{initializer list cannot be used on the left hand side of operator '*'}} \ + expected-error {{initializer list cannot be used on the right hand side of operator '*'}} +} + +struct S { + constexpr S(int a, int b) : a(a), b(b) {} + int a, b; +}; +struct T { + constexpr int operator=(S s) { return s.a; } + constexpr int operator+=(S s) { return s.b; } +}; +static_assert((T() = {4, 9}) == 4, ""); +static_assert((T() += {4, 9}) == 9, ""); + +int k1 = T() = { 1, 2 } = { 3, 4 }; // expected-error {{initializer list cannot be used on the left hand side of operator '='}} +int k2 = T() = { 1, 2 } + 1; // expected-error {{initializer list cannot be used on the left hand side of operator '+'}} diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index 2c6a46b3beaf2..054669ef788d6 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -1,7 +1,575 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -pedantic -verify -fcxx-exceptions %s -fconstexpr-depth 128 -triple i686-pc-linux-gnu + +// A conditional-expression is a core constant expression unless it involves one +// of the following as a potentially evaluated subexpression [...]: + +// - this (5.1.1 [expr.prim.general]) [Note: when evaluating a constant +// expression, function invocation substitution (7.1.5 [dcl.constexpr]) +// replaces each occurrence of this in a constexpr member function with a +// pointer to the class object. -end note]; +struct This { + int this1 : this1; // expected-error {{undeclared}} + int this2 : this->this1; // expected-error {{invalid}} + void this3() { + int n1[this->this1]; // expected-warning {{variable length array}} + int n2[this1]; // expected-warning {{variable length array}} + (void)n1, (void)n2; + } +}; + +// - an invocation of a function other than a constexpr constructor for a +// literal class or a constexpr function [ Note: Overload resolution (13.3) +// is applied as usual - end note ]; +struct NonConstexpr1 { + static int f() { return 1; } // expected-note {{here}} + int n : f(); // expected-error {{constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +}; +struct NonConstexpr2 { + constexpr NonConstexpr2(); // expected-note {{here}} + int n; +}; +struct NonConstexpr3 { + NonConstexpr3(); + int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}} +}; +struct NonConstexpr4 { + NonConstexpr4(); // expected-note {{declared here}} + int n; +}; +struct NonConstexpr5 { + int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}} +}; + +// - an invocation of an undefined constexpr function or an undefined +// constexpr constructor; +struct UndefinedConstexpr { + constexpr UndefinedConstexpr(); + static constexpr int undefinedConstexpr1(); // expected-note {{here}} + int undefinedConstexpr2 : undefinedConstexpr1(); // expected-error {{constant expression}} expected-note {{undefined function 'undefinedConstexpr1' cannot be used in a constant expression}} +}; + +// - an invocation of a constexpr function with arguments that, when substituted +// by function invocation substitution (7.1.5), do not produce a core constant +// expression; +namespace NonConstExprReturn { + static constexpr const int &id_ref(const int &n) { + return n; + } + struct NonConstExprFunction { + int n : id_ref(16); // ok + }; + constexpr const int *address_of(const int &a) { + return &a; + } + constexpr const int *return_param(int n) { // expected-note {{declared here}} + return address_of(n); + } + struct S { + int n : *return_param(0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}} + }; +} + +// - an invocation of a constexpr constructor with arguments that, when +// substituted by function invocation substitution (7.1.5), do not produce all +// constant expressions for the constructor calls and full-expressions in the +// mem-initializers (including conversions); +namespace NonConstExprCtor { + struct T { + constexpr T(const int &r) : + r(r) { + } + const int &r; + }; + constexpr int n = 0; + constexpr T t1(n); // ok + constexpr T t2(0); // expected-error {{must be initialized by a constant expression}} expected-note {{temporary created here}} expected-note {{reference to temporary is not a constant expression}} + + struct S { + int n : T(4).r; // ok + }; +} + +// - an invocation of a constexpr function or a constexpr constructor that would +// exceed the implementation-defined recursion limits (see Annex B); +namespace RecursionLimits { + constexpr int RecurseForever(int n) { + return n + RecurseForever(n+1); // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'RecurseForever(}} expected-note {{skipping 118 calls}} + } + struct AlsoRecurseForever { + constexpr AlsoRecurseForever(int n) : + n(AlsoRecurseForever(n+1).n) // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'AlsoRecurseForever(}} expected-note {{skipping 118 calls}} + {} + int n; + }; + struct S { + int k : RecurseForever(0); // expected-error {{constant expression}} expected-note {{in call to}} + int l : AlsoRecurseForever(0).n; // expected-error {{constant expression}} expected-note {{in call to}} + }; +} + +// DR1458: taking the address of an object of incomplete class type +namespace IncompleteClassTypeAddr { + struct S; + extern S s; + constexpr S *p = &s; // ok + static_assert(p, ""); + + extern S sArr[]; + constexpr S (*p2)[] = &sArr; // ok + + struct S { + constexpr S *operator&() { return nullptr; } + }; + constexpr S *q = &s; // ok + static_assert(!q, ""); +} + +// - an operation that would have undefined behavior [Note: including, for +// example, signed integer overflow (Clause 5 [expr]), certain pointer +// arithmetic (5.7 [expr.add]), division by zero (5.6 [expr.mul]), or certain +// shift operations (5.8 [expr.shift]) -end note]; +namespace UndefinedBehavior { + void f(int n) { + switch (n) { + case (int)4.4e9: // expected-error {{constant expression}} expected-note {{value 4.4E+9 is outside the range of representable values of type 'int'}} + case (int)0x80000000u: // ok + case (int)10000000000ll: // expected-note {{here}} + case (unsigned int)10000000000ll: // expected-error {{duplicate case value}} + case (int)(unsigned)(long long)4.4e9: // ok + case (int)(float)1e300: // expected-error {{constant expression}} expected-note {{value 1.0E+300 is outside the range of representable values of type 'float'}} + case (int)((float)1e37 / 1e30): // ok + case (int)(__fp16)65536: // expected-error {{constant expression}} expected-note {{value 65536 is outside the range of representable values of type 'half'}} + break; + } + } + + constexpr int int_min = ~0x7fffffff; + constexpr int minus_int_min = -int_min; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} + constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} + constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int int_min_mod_minus_1 = int_min % -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + + constexpr int shl_m1 = 0 << -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} + constexpr int shl_0 = 0 << 0; // ok + constexpr int shl_31 = 0 << 31; // ok + constexpr int shl_32 = 0 << 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type 'int' (32}} expected-warning {{>= width of type}} + constexpr int shl_unsigned_negative = unsigned(-3) << 1; // ok + constexpr int shl_unsigned_into_sign = 1u << 31; // ok + constexpr int shl_unsigned_overflow = 1024u << 31; // ok + constexpr int shl_signed_negative = (-3) << 1; // expected-error {{constant expression}} expected-note {{left shift of negative value -3}} + constexpr int shl_signed_ok = 1 << 30; // ok + constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457) + constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457) + constexpr int shl_signed_off_end = 2 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x100000000) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_off_end_2 = 0x7fffffff << 2; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x1FFFFFFFC) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_overflow = 1024 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{requires 43 bits to represent}} + constexpr int shl_signed_ok2 = 1024 << 20; // ok + + constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} + constexpr int shr_0 = 0 >> 0; // ok + constexpr int shr_31 = 0 >> 31; // ok + constexpr int shr_32 = 0 >> 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type}} expected-warning {{>= width of type}} + + struct S { + int m; + }; + constexpr S s = { 5 }; + constexpr const int *p = &s.m + 1; + constexpr const int &f(const int *q) { + return q[0]; + } + constexpr int n = (f(p), 0); // ok + struct T { + int n : f(p); // expected-error {{not an integral constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} + }; + + namespace Ptr { + struct A {}; + struct B : A { int n; }; + B a[3][3]; + constexpr B *p = a[0] + 4; // expected-error {{constant expression}} expected-note {{element 4 of array of 3 elements}} + B b = {}; + constexpr A *pa = &b + 1; // expected-error {{constant expression}} expected-note {{base class of pointer past the end}} + constexpr B *pb = (B*)((A*)&b + 1); // expected-error {{constant expression}} expected-note {{derived class of pointer past the end}} + constexpr const int *pn = &(&b + 1)->n; // expected-error {{constant expression}} expected-note {{field of pointer past the end}} + constexpr B *parr = &a[3][0]; // expected-error {{constant expression}} expected-note {{array element of pointer past the end}} + + constexpr A *na = nullptr; + constexpr B *nb = nullptr; + constexpr A &ra = *nb; // expected-error {{constant expression}} expected-note {{cannot access base class of null pointer}} + constexpr B &rb = (B&)*na; // expected-error {{constant expression}} expected-note {{cannot access derived class of null pointer}} + static_assert((A*)nb == 0, ""); + static_assert((B*)na == 0, ""); + constexpr const int &nf = nb->n; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}} + constexpr const int &np = (*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot access array element of null pointer}} + + struct C { + constexpr int f() { return 0; } + } constexpr c = C(); + constexpr int k1 = c.f(); // ok + constexpr int k2 = ((C*)nullptr)->f(); // expected-error {{constant expression}} expected-note {{cannot call member function on null pointer}} + constexpr int k3 = (&c)[1].f(); // expected-error {{constant expression}} expected-note {{cannot call member function on pointer past the end of object}} + C c2; + constexpr int k4 = c2.f(); // ok! + + constexpr int diff1 = &a[2] - &a[0]; + constexpr int diff2 = &a[1][3] - &a[1][0]; + constexpr int diff3 = &a[2][0] - &a[1][0]; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + static_assert(&a[2][0] == &a[1][3], ""); + constexpr int diff4 = (&b + 1) - &b; + constexpr int diff5 = &a[1][2].n - &a[1][0].n; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + constexpr int diff6 = &a[1][2].n - &a[1][2].n; + constexpr int diff7 = (A*)&a[0][1] - (A*)&a[0][0]; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + } + + namespace Overflow { + // Signed int overflow. + constexpr int n1 = 2 * 3 * 3 * 7 * 11 * 31 * 151 * 331; // ok + constexpr int n2 = 65536 * 32768; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n3 = n1 + 1; // ok + constexpr int n4 = n3 + 1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n5 = -65536 * 32768; // ok + constexpr int n6 = 3 * -715827883; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n7 = -n3 + -1; // ok + constexpr int n8 = -1 + n7; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n9 = n3 - 0; // ok + constexpr int n10 = n3 - -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n11 = -1 - n3; // ok + constexpr int n12 = -2 - n3; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }} + constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }} + constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }} + constexpr signed char c1 = 100 * 2; // ok + constexpr signed char c2 = '\x64' * '\2'; // also ok + constexpr long long ll1 = 0x7fffffffffffffff; // ok + constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }} + constexpr long long ll3 = -ll1 - 1; // ok + constexpr long long ll4 = ll3 - 1; // expected-error {{constant}} expected-note {{ -9223372036854775809 }} + constexpr long long ll5 = ll3 * ll3; // expected-error {{constant}} expected-note {{ 85070591730234615865843651857942052864 }} + + // Yikes. + char melchizedek[2200000000]; + typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t; + constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok + constexpr ptrdiff_t d2 = &melchizedek[0x80000000u] - &melchizedek[0]; // expected-error {{constant expression}} expected-note {{ 2147483648 }} + constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok + constexpr ptrdiff_t d4 = &melchizedek[0] - &melchizedek[0x80000001u]; // expected-error {{constant expression}} expected-note {{ -2147483649 }} + + // Unsigned int overflow. + static_assert(65536u * 65536u == 0u, ""); // ok + static_assert(4294967295u + 1u == 0u, ""); // ok + static_assert(0u - 1u == 4294967295u, ""); // ok + static_assert(~0u * ~0u == 1u, ""); // ok + + // Floating-point overflow and NaN. + constexpr float f1 = 1e38f * 3.4028f; // ok + constexpr float f2 = 1e38f * 3.4029f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f3 = 1e38f / -.2939f; // ok + constexpr float f4 = 1e38f / -.2938f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f5 = 2e38f + 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f6 = -2e38f - 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f7 = 0.f / 0.f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces a NaN}} + } +} + +// - a lambda-expression (5.1.2); +struct Lambda { + // FIXME: clang crashes when trying to parse this! Revisit this check once + // lambdas are fully implemented. + //int n : []{ return 1; }(); +}; + +// - an lvalue-to-rvalue conversion (4.1) unless it is applied to +namespace LValueToRValue { + // - a non-volatile glvalue of integral or enumeration type that refers to a + // non-volatile const object with a preceding initialization, initialized + // with a constant expression [Note: a string literal (2.14.5 [lex.string]) + // corresponds to an array of such objects. -end note], or + volatile const int vi = 1; // expected-note 2{{here}} + const int ci = 1; + volatile const int &vrci = ci; + static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + + // - a non-volatile glvalue of literal type that refers to a non-volatile + // object defined with constexpr, or that refers to a sub-object of such an + // object, or + struct V { + constexpr V() : v(1) {} + volatile int v; // expected-note {{not literal because}} + }; + constexpr V v; // expected-error {{non-literal type}} + struct S { + constexpr S(int=0) : i(1), v(const_cast<volatile int&>(vi)) {} + constexpr S(const S &s) : i(2), v(const_cast<volatile int&>(vi)) {} + int i; + volatile int &v; + }; + constexpr S s; // ok + constexpr volatile S vs; // expected-note {{here}} + constexpr const volatile S &vrs = s; // ok + static_assert(s.i, ""); + static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(s.v), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}} + static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + + // - a non-volatile glvalue of literal type that refers to a non-volatile + // temporary object whose lifetime has not ended, initialized with a + // constant expression; + constexpr volatile S f() { return S(); } + static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here! + static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} +} + +// DR1312: The proposed wording for this defect has issues, so we ignore this +// bullet and instead prohibit casts from pointers to cv void (see core-20842 +// and core-20845). +// +// - an lvalue-to-rvalue conversion (4.1 [conv.lval]) that is applied to a +// glvalue of type cv1 T that refers to an object of type cv2 U, where T and U +// are neither the same type nor similar types (4.4 [conv.qual]); + +// - an lvalue-to-rvalue conversion (4.1) that is applied to a glvalue that +// refers to a non-active member of a union or a subobject thereof; +namespace LValueToRValueUnion { + // test/SemaCXX/constant-expression-cxx11.cpp contains more thorough testing + // of this. + union U { int a, b; } constexpr u = U(); + static_assert(u.a == 0, ""); + constexpr const int *bp = &u.b; + constexpr int b = *bp; // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}} + + extern const U pu; + constexpr const int *pua = &pu.a; + constexpr const int *pub = &pu.b; + constexpr U pu = { .b = 1 }; // expected-warning {{C99 feature}} + constexpr const int a2 = *pua; // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}} + constexpr const int b2 = *pub; // ok +} + +// - an id-expression that refers to a variable or data member of reference type +// unless the reference has a preceding initialization, initialized with a +// constant expression; +namespace References { + const int a = 2; + int &b = *const_cast<int*>(&a); + int c = 10; // expected-note 2 {{here}} + int &d = c; + constexpr int e = 42; + int &f = const_cast<int&>(e); + extern int &g; + constexpr int &h(); // expected-note {{here}} + int &i = h(); // expected-note {{here}} + constexpr int &j() { return b; } + int &k = j(); + + struct S { + int A : a; + int B : b; + int C : c; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + int D : d; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + int D2 : &d - &c + 1; + int E : e / 2; + int F : f - 11; + int G : g; // expected-error {{constant expression}} + int H : h(); // expected-error {{constant expression}} expected-note {{undefined function 'h'}} + int I : i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}} + int J : j(); + int K : k; + }; +} + +// - a dynamic_cast (5.2.7); +namespace DynamicCast { + struct S { int n; }; + constexpr S s { 16 }; + struct T { + int n : dynamic_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{dynamic_cast}} + }; +} + +// - a reinterpret_cast (5.2.10); +namespace ReinterpretCast { + struct S { int n; }; + constexpr S s { 16 }; + struct T { + int n : reinterpret_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} + }; + struct U { + int m : (long)(S*)6; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} + }; +} + +// - a pseudo-destructor call (5.2.4); +namespace PseudoDtor { + int k; + typedef int I; + struct T { + int n : (k.~I(), 0); // expected-error {{constant expression}} + }; +} + +// - increment or decrement operations (5.2.6, 5.3.2); +namespace IncDec { + int k = 2; + struct T { + int n : ++k; // expected-error {{constant expression}} + int m : --k; // expected-error {{constant expression}} + }; +} + +// - a typeid expression (5.2.8) whose operand is of a polymorphic class type; +namespace std { + struct type_info { + virtual ~type_info(); + const char *name; + }; +} +namespace TypeId { + struct S { virtual void f(); }; + constexpr S *p = 0; + constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} expected-note {{typeid applied to expression of polymorphic type 'TypeId::S'}} + + struct T {} t; + constexpr const std::type_info &ti2 = typeid(t); +} + +// - a new-expression (5.3.4); +// - a delete-expression (5.3.5); +namespace NewDelete { + int *p = 0; + struct T { + int n : *new int(4); // expected-error {{constant expression}} + int m : (delete p, 2); // expected-error {{constant expression}} + }; +} + +// - a relational (5.9) or equality (5.10) operator where the result is +// unspecified; +namespace UnspecifiedRelations { + int a, b; + constexpr int *p = &a, *q = &b; + // C++11 [expr.rel]p2: If two pointers p and q of the same type point to + // different objects that are not members of the same array or to different + // functions, or if only one of them is null, the results of p<q, p>q, p<=q, + // and p>=q are unspecified. + constexpr bool u1 = p < q; // expected-error {{constant expression}} + constexpr bool u2 = p > q; // expected-error {{constant expression}} + constexpr bool u3 = p <= q; // expected-error {{constant expression}} + constexpr bool u4 = p >= q; // expected-error {{constant expression}} + constexpr bool u5 = p < 0; // expected-error {{constant expression}} + constexpr bool u6 = p <= 0; // expected-error {{constant expression}} + constexpr bool u7 = p > 0; // expected-error {{constant expression}} + constexpr bool u8 = p >= 0; // expected-error {{constant expression}} + constexpr bool u9 = 0 < q; // expected-error {{constant expression}} + constexpr bool u10 = 0 <= q; // expected-error {{constant expression}} + constexpr bool u11 = 0 > q; // expected-error {{constant expression}} + constexpr bool u12 = 0 >= q; // expected-error {{constant expression}} + void f(), g(); + + constexpr void (*pf)() = &f, (*pg)() = &g; + constexpr bool u13 = pf < pg; // expected-error {{constant expression}} + constexpr bool u14 = pf == pg; + + // If two pointers point to non-static data members of the same object with + // different access control, the result is unspecified. + struct A { + public: + constexpr A() : a(0), b(0) {} + int a; + constexpr bool cmp() { return &a < &b; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'A' with differing access specifiers (public vs private) has unspecified value}} + private: + int b; + }; + class B { + public: + A a; + constexpr bool cmp() { return &a.a < &b.a; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'B' with differing access specifiers (public vs protected) has unspecified value}} + protected: + A b; + }; + + // If two pointers point to different base sub-objects of the same object, or + // one points to a base subobject and the other points to a member, the result + // of the comparison is unspecified. This is not explicitly called out by + // [expr.rel]p2, but is covered by 'Other pointer comparisons are + // unspecified'. + struct C { + int c[2]; + }; + struct D { + int d; + }; + struct E : C, D { + struct Inner { + int f; + } e; + } e; + constexpr bool base1 = &e.c[0] < &e.d; // expected-error {{constant expression}} expected-note {{comparison of addresses of subobjects of different base classes has unspecified value}} + constexpr bool base2 = &e.c[1] < &e.e.f; // expected-error {{constant expression}} expected-note {{comparison of address of base class subobject 'C' of class 'E' to field 'e' has unspecified value}} + constexpr bool base3 = &e.e.f < &e.d; // expected-error {{constant expression}} expected-note {{comparison of address of base class subobject 'D' of class 'E' to field 'e' has unspecified value}} + + // [expr.rel]p3: Pointers to void can be compared [...] if both pointers + // represent the same address or are both the null pointer [...]; otherwise + // the result is unspecified. + struct S { int a, b; } s; + constexpr void *null = 0; + constexpr void *pv = (void*)&s.a; + constexpr void *qv = (void*)&s.b; + constexpr bool v1 = null < 0; + constexpr bool v2 = null < pv; // expected-error {{constant expression}} + constexpr bool v3 = null == pv; // ok + constexpr bool v4 = qv == pv; // ok + constexpr bool v5 = qv >= pv; // expected-error {{constant expression}} expected-note {{unequal pointers to void}} + constexpr bool v6 = qv > null; // expected-error {{constant expression}} + constexpr bool v7 = qv <= (void*)&s.b; // ok + constexpr bool v8 = qv > (void*)&s.a; // expected-error {{constant expression}} expected-note {{unequal pointers to void}} +} + +// - an assignment or a compound assignment (5.17); or +namespace Assignment { + int k; + struct T { + int n : (k = 9); // expected-error {{constant expression}} + int m : (k *= 2); // expected-error {{constant expression}} + }; + + struct Literal { + constexpr Literal(const char *name) : name(name) {} + const char *name; + }; + struct Expr { + constexpr Expr(Literal l) : IsLiteral(true), l(l) {} + bool IsLiteral; + union { + Literal l; + // ... + }; + }; + struct MulEq { + constexpr MulEq(Expr a, Expr b) : LHS(a), RHS(b) {} + Expr LHS; + Expr RHS; + }; + constexpr MulEq operator*=(Expr a, Expr b) { return MulEq(a, b); } + Literal a("a"); + Literal b("b"); + MulEq c = a *= b; // ok +} + +// - a throw-expression (15.1) +namespace Throw { + struct S { + int n : (throw "hello", 10); // expected-error {{constant expression}} + }; +} // PR9999 -template<bool v> +template<unsigned int v> class bitWidthHolding { public: static const @@ -23,3 +591,6 @@ struct and_or { static const bool and_value = and_or<true>::and_value; static const bool or_value = and_or<true>::or_value; + +static_assert(and_value == false, ""); +static_assert(or_value == true, ""); diff --git a/test/CXX/expr/expr.const/p3-0x-nowarn.cpp b/test/CXX/expr/expr.const/p3-0x-nowarn.cpp new file mode 100644 index 0000000000000..c891374519fba --- /dev/null +++ b/test/CXX/expr/expr.const/p3-0x-nowarn.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-c++11-narrowing -verify %s + +// <rdar://problem/11121178> +void f(int x) { + switch (x) { + case 0x80000001: break; + } +} diff --git a/test/CXX/expr/expr.const/p3-0x.cpp b/test/CXX/expr/expr.const/p3-0x.cpp new file mode 100644 index 0000000000000..6ddd11bcee268 --- /dev/null +++ b/test/CXX/expr/expr.const/p3-0x.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// A converted constant expression of type T is a core constant expression, +int nonconst = 8; // expected-note 3 {{here}} +enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}} +template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} +void NonConstF() { + switch (nonconst) { + case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}} + break; + } + return; +} + +// implicitly converted to a prvalue of type T, where the converted expression +// is a literal constant expression + +bool a(int n) { + constexpr char vowels[] = "aeiou"; + switch (n) { + case vowels[0]: + case vowels[1]: + case vowels[2]: + case vowels[3]: + case vowels[4]: + static_assert(!vowels[5], "unexpected number of vowels"); + return true; + } + return false; +} + +// and the implicit conversion sequence contains only +// +// user-defined conversions, +struct S { constexpr operator int() const { return 5; } }; +enum E : unsigned char { E5 = S(), E6, E10 = S() * 2, E1 = E5 / 5 }; + +// lvalue-to-rvalue conversions, +const E e10 = E10; +template<E> struct T {}; +T<e10> s10; + +// integral promotions, and +enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 }; + +// integral conversions other than narrowing conversions +int b(unsigned n) { + switch (n) { + case E6: + case EE::EE32: // expected-error {{not implicitly convertible}} + case (int)EE::EE32: + case 1000: + case (long long)1e10: // expected-error {{case value evaluates to 10000000000, which cannot be narrowed to type 'unsigned int'}} + case -3: // expected-error {{case value evaluates to -3, which cannot be narrowed to type 'unsigned int'}} + return n; + } + return 0; +} +enum class EEE : unsigned short { + a = E6, + b = EE::EE32, // expected-error {{not implicitly convertible}} + c = (int)EE::EE32, + d = 1000, + e = 123456, // expected-error {{enumerator value evaluates to 123456, which cannot be narrowed to type 'unsigned short'}} + f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be narrowed to type 'unsigned short'}} +}; +template<unsigned char> using A = int; +using Int = A<E6>; +using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}} +using Int = A<(int)EE::EE32>; +using Int = A<200>; +using Int = A<1000>; // expected-error {{template argument evaluates to 1000, which cannot be narrowed to type 'unsigned char'}} +using Int = A<-3>; // expected-error {{template argument evaluates to -3, which cannot be narrowed to type 'unsigned char'}} + +// Note, conversions from integral or unscoped enumeration types to bool are +// integral conversions as well as boolean conversions. +template<typename T, T v> struct Val { static constexpr T value = v; }; +static_assert(Val<bool, E1>::value == 1, ""); // ok +static_assert(Val<bool, '\0'>::value == 0, ""); // ok +static_assert(Val<bool, U'\1'>::value == 1, ""); // ok +static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}} + +// (no other conversions are permitted) +using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}} +enum B : bool { + True = &a, // expected-error {{conversion from 'bool (*)(int)' to 'bool' is not allowed in a converted constant expression}} + False = nullptr // expected-error {{conversion from 'nullptr_t' to 'bool' is not allowed in a converted constant expression}} +}; +void c() { + // Note, promoted type of switch is 'int'. + switch (bool b = a(5)) { // expected-warning {{boolean value}} + case 0.0f: // expected-error {{conversion from 'float' to 'int' is not allowed in a converted constant expression}} + break; + } +} +template<bool B> int f() { return B; } +template int f<&S::operator int>(); // expected-error {{does not refer to a function template}} +template int f<(bool)&S::operator int>(); + +int n = Val<bool, &S::operator int>::value; // expected-error {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}} + +namespace NonConstLValue { + struct S { + constexpr operator int() { return 10; } + }; + S s; // not constexpr + // Under the FDIS, this is not a converted constant expression. + // Under the new proposed wording, it is. + enum E : char { e = s }; +} diff --git a/test/CXX/expr/expr.const/p5-0x.cpp b/test/CXX/expr/expr.const/p5-0x.cpp new file mode 100644 index 0000000000000..60fabe37e2bbc --- /dev/null +++ b/test/CXX/expr/expr.const/p5-0x.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// If an expression of literal class type is used in a context where an integral +// constant expression is required, then that class type shall have a single +// non-explicit conversion function to an integral or unscoped enumeration type +namespace std_example { + +struct A { + constexpr A(int i) : val(i) { } + constexpr operator int() { return val; } + constexpr operator long() { return 43; } +private: + int val; +}; +template<int> struct X { }; +constexpr A a = 42; +X<a> x; // ok, unique conversion to int +int ary[a]; // expected-error {{size of array has non-integer type 'const std_example::A'}} + +} + +struct OK { + constexpr OK() {} + constexpr operator int() { return 8; } +} constexpr ok; +extern struct Incomplete incomplete; // expected-note 4{{forward decl}} +struct Explicit { + constexpr Explicit() {} + constexpr explicit operator int() { return 4; } // expected-note 4{{here}} +} constexpr expl; +struct Ambiguous { + constexpr Ambiguous() {} + constexpr operator int() { return 2; } // expected-note 4{{here}} + constexpr operator long() { return 1; } // expected-note 4{{here}} +} constexpr ambig; + +constexpr int test_ok = ok; // ok +constexpr int test_explicit(expl); // ok +constexpr int test_ambiguous = ambig; // ok + +static_assert(test_ok == 8, ""); +static_assert(test_explicit == 4, ""); +static_assert(test_ambiguous == 2, ""); + +// [expr.new]p6: Every constant-expression in a noptr-new-declarator shall be +// an integral constant expression +auto new1 = new int[1][ok]; +auto new2 = new int[1][incomplete]; // expected-error {{incomplete}} +auto new3 = new int[1][expl]; // expected-error {{explicit conversion}} +auto new4 = new int[1][ambig]; // expected-error {{ambiguous conversion}} + +// [dcl.enum]p5: If the underlying type is not fixed [...] the initializing +// value [...] shall be an integral constant expression. +enum NotFixed { + enum1 = ok, + enum2 = incomplete, // expected-error {{incomplete}} + enum3 = expl, // expected-error {{explicit conversion}} + enum4 = ambig // expected-error {{ambiguous conversion}} +}; + +// [dcl.align]p2: When the alignment-specifier is of the form +// alignas(assignment-expression), the assignment-expression shall be an +// integral constant expression +int alignas(ok) alignas1; +int alignas(incomplete) alignas2; // expected-error {{incomplete}} +int alignas(expl) alignas3; // expected-error {{explicit conversion}} +int alignas(ambig) alignas4; // expected-error {{ambiguous conversion}} + +// [dcl.array]p1: If the constant-expression is present, it shall be an integral +// constant expression +// FIXME: The VLA recovery results in us giving diagnostics which aren't great +// here. +int array1[ok]; +int array2[incomplete]; // expected-error {{non-integer type}} +int array3[expl]; // expected-error {{non-integer type}} +int array4[ambig]; // expected-error {{non-integer type}} + +// [class.bit]p1: The constasnt-expression shall be an integral constant +// expression +struct Bitfields { + int bitfield1 : ok; + int bitfield2 : incomplete; // expected-error {{incomplete}} + int bitfield3 : expl; // expected-error {{explicit conversion}} + int bitfield4 : ambig; // expected-error {{ambiguous conversion}} +}; diff --git a/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp b/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp new file mode 100644 index 0000000000000..253744e23f572 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct foo { + foo(); + foo(int); +}; + +int func(foo& f) { + decltype(foo())(); + f = (decltype(foo()))5; + return decltype(3)(5); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp new file mode 100644 index 0000000000000..249c976460897 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}} + int *m = &n; // ok + + int n = f(); // ok + int f(); +}; + +int i = sizeof(S::m); // ok +int j = sizeof(S::m + 42); // ok + + +struct T { + int n; + static void f() { + int a[n]; // expected-error {{invalid use of member 'n' in static member function}} + int b[sizeof n]; // ok + } +}; + +// Make sure the rule for unevaluated operands works correctly with typeid. +namespace std { + class type_info; +} +class Poly { virtual ~Poly(); }; +const std::type_info& k = typeid(S::m); +const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of non-static data member}} +const std::type_info& n = typeid(*(Poly*)(0*sizeof S::m)); + +namespace PR11956 { + struct X { char a; }; + struct Y { int f() { return sizeof(X::a); } }; // ok + + struct A { enum E {} E; }; + struct B { int f() { return sizeof(A::E); } }; // ok +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp new file mode 100644 index 0000000000000..4e57b74f08a08 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + S *p = this; // ok + decltype(this) q; // expected-error {{invalid use of 'this' outside of a non-static member function}} + + int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a non-static member function}} + int sz = sizeof(this); // ok +}; + +namespace CaptureThis { + struct X { + int n = 10; + int m = [&]{return n + 1; }(); + int o = [&]{return this->m + 1; }(); + int p = [&]{return [&](int x) { return this->m + x;}(o); }(); + }; + + X x; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp new file mode 100644 index 0000000000000..5b3a004056b52 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct global { +}; + +namespace PR10127 { + struct outer { + struct middle { + struct inner { + int func(); + int i; + }; + struct inner2 { + }; + struct inner3 { + }; + int mfunc(); + }; + typedef int td_int; + }; + + struct str { + operator decltype(outer::middle::inner()) (); + operator decltype(outer::middle())::inner2 (); + operator decltype(outer())::middle::inner3 (); + str(int (decltype(outer::middle::inner())::*n)(), + int (decltype(outer::middle())::inner::*o)(), + int (decltype(outer())::middle::inner::*p)()); + }; + + decltype(outer::middle::inner()) a; + void scope() { + a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}} + a.decltype(outer::middle::inner())::func(); + a.decltype(outer::middle())::inner::func(); + a.decltype(outer())::middle::inner::func(); + + a.decltype(outer())::middle::inner::~inner(); + + decltype(outer())::middle::inner().func(); + } + decltype(outer::middle())::inner b; + decltype(outer())::middle::inner c; + decltype(outer())::fail d; // expected-error{{no type named 'fail' in 'PR10127::outer'}} + decltype(outer())::fail::inner e; // expected-error{{no member named 'fail' in 'PR10127::outer'}} + decltype()::fail f; // expected-error{{expected expression}} + decltype()::middle::fail g; // expected-error{{expected expression}} + + decltype(int()) h; + decltype(int())::PR10127::outer i; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}} + decltype(int())::global j; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}} + + outer::middle k = decltype(outer())::middle(); + outer::middle::inner l = decltype(outer())::middle::inner(); + + template<typename T> + struct templ { + typename decltype(T())::middle::inner x; // expected-error{{type 'decltype(int())' (aka 'int') cannot be used prior to '::' because it has no members}} + }; + + template class templ<int>; // expected-note{{in instantiation of template class 'PR10127::templ<int>' requested here}} + template class templ<outer>; + + enum class foo { + bar, + baz + }; + + foo m = decltype(foo::bar)::baz; + + enum E { + }; + struct bar { + enum E : decltype(outer())::td_int(4); + enum F : decltype(outer())::td_int; + enum G : decltype; // expected-error{{expected '(' after 'decltype'}} + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm new file mode 100644 index 0000000000000..0c3fdb2d80eb3 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++11 -fblocks %s -verify + +void block_capture_errors() { + __block int var; // expected-note 2{{'var' declared here}} + (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} + + (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} +} + +void conversion_to_block(int captured) { + int (^b1)(int) = [=](int x) { return x + captured; }; + + const auto lambda = [=](int x) { return x + captured; }; + int (^b2)(int) = lambda; +} + +template<typename T> +class ConstCopyConstructorBoom { +public: + ConstCopyConstructorBoom(ConstCopyConstructorBoom&); + + ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) { + T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} + } + + void foo() const; +}; + +void conversion_to_block_init(ConstCopyConstructorBoom<int> boom, + ConstCopyConstructorBoom<float> boom2) { + const auto& lambda1([=] { boom.foo(); }); // okay + + const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}} + void (^block)(void) = lambda2; +} + + +void nesting() { + int array[7]; // expected-note 2{{'array' declared here}} + [=] () mutable { + [&] { + ^ { + int i = array[2]; + i += array[3]; + }(); + }(); + }(); + + [&] { + [=] () mutable { + ^ { + int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}} + i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}} + }(); + }(); + }(); +} + +namespace overloading { + void bool_conversion() { + if ([](){}) { + } + + bool b = []{}; + b = (bool)[]{}; + } + + void conversions() { + int (*fp)(int) = [](int x) { return x + 1; }; + fp = [](int x) { return x + 1; }; + + typedef int (*func_ptr)(int); + fp = (func_ptr)[](int x) { return x + 1; }; + + int (^bp)(int) = [](int x) { return x + 1; }; + bp = [](int x) { return x + 1; }; + + typedef int (^block_ptr)(int); + bp = (block_ptr)[](int x) { return x + 1; }; + } + + int &accept_lambda_conv(int (*fp)(int)); + float &accept_lambda_conv(int (^bp)(int)); + + void call_with_lambda() { + int &ir = accept_lambda_conv([](int x) { return x + 1; }); + } +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp new file mode 100644 index 0000000000000..5dac886d4d1dd --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -Wno-lambda-extensions -verify + +void defargs() { + auto l1 = [](int i, int j = 17, int k = 18) { return i + j + k; }; + int i1 = l1(1); + int i2 = l1(1, 2); + int i3 = l1(1, 2, 3); +} + + +void defargs_errors() { + auto l1 = [](int i, + int j = 17, + int k) { }; // expected-error{{missing default argument on parameter 'k'}} + + auto l2 = [](int i, int j = i) {}; // expected-error{{default argument references parameter 'i'}} + + int foo; + auto l3 = [](int i = foo) {}; // expected-error{{default argument references local variable 'foo' of enclosing function}} +} + +struct NonPOD { + NonPOD(); + NonPOD(const NonPOD&); + ~NonPOD(); +}; + +struct NoDefaultCtor { + NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}} + ~NoDefaultCtor(); +}; + +template<typename T> +void defargs_in_template_unused(T t) { + auto l1 = [](const T& value = T()) { }; + l1(t); +} + +template void defargs_in_template_unused(NonPOD); +template void defargs_in_template_unused(NoDefaultCtor); + +template<typename T> +void defargs_in_template_used() { + auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} + l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}} +} + +template void defargs_in_template_used<NonPOD>(); +template void defargs_in_template_used<NoDefaultCtor>(); // expected-note{{in instantiation of function template specialization}} + diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp new file mode 100644 index 0000000000000..245e27042be35 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +int GlobalVar; // expected-note {{declared here}} + +namespace N { + int AmbiguousVar; // expected-note {{candidate}} +} +int AmbiguousVar; // expected-note {{candidate}} +using namespace N; + +class X0 { + int Member; + + static void Overload(int); + void Overload(); + virtual X0& Overload(float); + + void explicit_capture() { + int variable; // expected-note {{declared here}} + (void)[&Overload] () {}; // expected-error {{does not name a variable}} + (void)[&GlobalVar] () {}; // expected-error {{does not have automatic storage duration}} + (void)[&AmbiguousVar] () {}; // expected-error {{reference to 'AmbiguousVar' is ambiguous}} + (void)[&Variable] () {}; // expected-error {{use of undeclared identifier 'Variable'; did you mean 'variable'}} + } +}; + +void test_reaching_scope() { + int local; // expected-note{{declared here}} + static int local_static; // expected-note{{'local_static' declared here}} + (void)[=]() { + struct InnerLocal { + void member() { + (void)[local, // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}} + local_static]() { // expected-error{{'local_static' cannot be captured because it does not have automatic storage duration}} + return 0; + }; + } + }; + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp new file mode 100644 index 0000000000000..d265dd757398e --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +void test_reaching_scope() { + int local; // expected-note{{declared here}} + static int local_static; + (void)[=]() { + struct InnerLocal { + void member() { + (void)[=]() { + return local + // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}} + local_static; + }; + } + }; + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp new file mode 100644 index 0000000000000..4a2a4f3d73539 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +void odr_used() { + int i = 17; + [i]{}(); +} + +struct ReachingThis { + static void static_foo() { + (void)[this](){}; // expected-error{{'this' cannot be captured in this context}} + + struct Local { + int i; + + void bar() { + (void)[this](){}; + (void)[&](){i = 7; }; + } + }; + } + + void foo() { + (void)[this](){}; + + struct Local { + int i; + + static void static_bar() { + (void)[this](){}; // expected-error{{'this' cannot be captured in this context}} + (void)[&](){i = 7; }; // expected-error{{invalid use of member 'i' in static member function}} + } + }; + } +}; + +void immediately_enclosing(int i) { // expected-note{{'i' declared here}} + [i]() { + [i] {}(); + }(); + + [=]() { + [i] {}(); + }(); + + []() { // expected-note{{lambda expression begins here}} + [i] {}(); // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} + }(); +} + +void f1(int i) { // expected-note{{declared here}} + int const N = 20; + auto m1 = [=]{ + int const M = 30; + auto m2 = [i]{ + int x[N][M]; + x[0][0] = i; + }; + (void)N; + (void)M; + (void)m2; + }; + struct s1 { + int f; + void work(int n) { // expected-note{{declared here}} + int m = n*n; + int j = 40; // expected-note{{declared here}} + auto m3 = [this,m] { // expected-note 3{{lambda expression begins here}} + auto m4 = [&,j] { // expected-error{{variable 'j' cannot be implicitly captured in a lambda with no capture-default specified}} + int x = n; // expected-error{{variable 'n' cannot be implicitly captured in a lambda with no capture-default specified}} + x += m; + x += i; // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} + x += f; + }; + }; + } + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp new file mode 100644 index 0000000000000..8bb707e0dbc75 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +void f2() { + int i = 1; + void g1(int = ([i]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g2(int = ([i]{ return 0; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g3(int = ([=]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g4(int = ([=]{ return 0; })()); + void g5(int = ([]{ return sizeof i; })()); +} + +namespace lambda_in_default_args { + int f(int = [] () -> int { int n; return ++n; } ()); + template<typename T> T g(T = [] () -> T { T n; return ++n; } ()); + int k = f() + g<int>(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp new file mode 100644 index 0000000000000..678fa4b964d49 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +template<typename T> void capture(const T&); + +class NonCopyable { + NonCopyable(const NonCopyable&); // expected-note 2 {{implicitly declared private here}} +public: + void foo() const; +}; + +class NonConstCopy { +public: + NonConstCopy(NonConstCopy&); // expected-note{{would lose const}} +}; + +void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) { + (void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}} + (void)[=] { + ncr.foo(); // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}} + }(); + + [nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}} +} + +struct NonTrivial { + NonTrivial(); + NonTrivial(const NonTrivial &); + ~NonTrivial(); +}; + +struct CopyCtorDefault { + CopyCtorDefault(); + CopyCtorDefault(const CopyCtorDefault&, NonTrivial nt = NonTrivial()); + + void foo() const; +}; + +void capture_with_default_args(CopyCtorDefault cct) { + (void)[=] () -> void { cct.foo(); }; +} + +struct ExpectedArrayLayout { + CopyCtorDefault array[3]; +}; + +void capture_array() { + CopyCtorDefault array[3]; + auto x = [=]() -> void { + capture(array[0]); + }; + static_assert(sizeof(x) == sizeof(ExpectedArrayLayout), "layout mismatch"); +} + +// Check for the expected non-static data members. + +struct ExpectedLayout { + char a; + short b; +}; + +void test_layout(char a, short b) { + auto x = [=] () -> void { + capture(a); + capture(b); + }; + static_assert(sizeof(x) == sizeof(ExpectedLayout), "Layout mismatch!"); +} + +struct ExpectedThisLayout { + ExpectedThisLayout* a; + void f() { + auto x = [this]() -> void {}; + static_assert(sizeof(x) == sizeof(ExpectedThisLayout), "Layout mismatch!"); + } +}; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp new file mode 100644 index 0000000000000..c4deba9c97439 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +class NonCopyable { + NonCopyable(const NonCopyable&); +}; + +void capture_by_ref(NonCopyable nc, NonCopyable &ncr) { + int array[3]; + (void)[&nc] () -> void {}; + (void)[&ncr] () -> void {}; + (void)[&array] () -> void {}; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp new file mode 100644 index 0000000000000..0cf01ade4313b --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + + +struct X { + X(const X&) = delete; // expected-note 2{{explicitly marked deleted}} + X(X&); +}; + +void test_capture(X x) { + [x] { }(); // okay: non-const copy ctor + + [x] { + [x] { // expected-error{{call to deleted constructor of 'X'}} + }(); + }(); + + [x] { + [&x] { + [x] { // expected-error{{call to deleted constructor of 'const X'}} + }(); + }(); + }(); + + int a; + [=]{ + [&] { + int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + }(); + }(); + + [=]{ + [&a] { + [&] { + int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + }(); + }(); + }(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp new file mode 100644 index 0000000000000..930a4b32fa06c --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +void f3() { + float x, &r = x; + int i; + int &ir = i; + const int &irc = i; + + [=,&irc,&ir] { + static_assert(is_same<decltype(((r))), float const&>::value, + "should be const float&"); + static_assert(is_same<decltype(x), float>::value, "should be float"); + static_assert(is_same<decltype((x)), const float&>::value, + "should be const float&"); + static_assert(is_same<decltype(r), float&>::value, "should be float&"); + static_assert(is_same<decltype(ir), int&>::value, "should be int&"); + static_assert(is_same<decltype((ir)), int&>::value, "should be int&"); + static_assert(is_same<decltype(irc), const int&>::value, + "should be const int&"); + static_assert(is_same<decltype((irc)), const int&>::value, + "should be const int&"); + }(); + + [=] { + [=] () mutable { + static_assert(is_same<decltype(x), float>::value, "should be float"); + static_assert(is_same<decltype((x)), float&>::value, + "should be float&"); + }(); + }(); + + [&i] { + static_assert(is_same<decltype((i)), int&>::value, "should be int&"); + }(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp new file mode 100644 index 0000000000000..6fe3b25259fd7 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +struct MoveOnly { + MoveOnly(MoveOnly&&); + MoveOnly(const MoveOnly&); +}; + +template<typename T> T &&move(T&); +void test_special_member_functions(MoveOnly mo, int i) { + auto lambda1 = [i]() { }; // expected-note 2 {{lambda expression begins here}} + + // Default constructor + decltype(lambda1) lambda2; // expected-error{{call to implicitly-deleted default constructor of 'decltype(lambda1)' (aka '<lambda}} + + // Copy assignment operator + lambda1 = lambda1; // expected-error{{overload resolution selected implicitly-deleted copy assignment operator}} + + // Move assignment operator + lambda1 = move(lambda1); + + // Copy constructor + decltype(lambda1) lambda3 = lambda1; + decltype(lambda1) lambda4(lambda1); + + // Move constructor + decltype(lambda1) lambda5 = move(lambda1); + decltype(lambda1) lambda6(move(lambda1)); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp new file mode 100644 index 0000000000000..c6ed308d79a10 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +// prvalue +void prvalue() { + auto&& x = []()->void { }; + auto& y = []()->void { }; // expected-error{{cannot bind to a temporary of type}} +} + +namespace std { + class type_info; +} + +struct P { + virtual ~P(); +}; + +void unevaluated_operand(P &p, int i) { + int i2 = sizeof([]()->void{}()); // expected-error{{lambda expression in an unevaluated operand}} + const std::type_info &ti1 = typeid([&]() -> P& { return p; }()); + const std::type_info &ti2 = typeid([&]() -> int { return i; }()); // expected-error{{lambda expression in an unevaluated operand}} +} + +template<typename T> +struct Boom { + Boom(const Boom&) { + T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'int'}} + } + void tickle() const; +}; + +void odr_used(P &p, Boom<int> boom_int, Boom<float> boom_float, + Boom<double> boom_double) { + const std::type_info &ti1 + = typeid([=,&p]() -> P& { boom_int.tickle(); return p; }()); // expected-note{{in instantiation of member function 'Boom<int>::Boom' requested here}} + const std::type_info &ti2 + = typeid([=]() -> int { boom_float.tickle(); return 0; }()); // expected-error{{lambda expression in an unevaluated operand}} \ + // expected-note{{in instantiation of member function 'Boom<float>::Boom' requested here}} + + auto foo = [=]() -> int { boom_double.tickle(); return 0; }; // expected-note{{in instantiation of member function 'Boom<double>::Boom' requested here}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp new file mode 100644 index 0000000000000..4487cfc4ba282 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +template<typename T> +void destroy(T* ptr) { + ptr->~T(); + (*ptr).~T(); +} + +void destructor() { + auto lambda = []{}; + destroy(&lambda); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp new file mode 100644 index 0000000000000..7139058cd0891 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +struct DirectInitOnly { + explicit DirectInitOnly(DirectInitOnly&); +}; + +void direct_init_capture(DirectInitOnly &dio) { + [dio] {}(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp new file mode 100644 index 0000000000000..174db257c891b --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void print(); + +template<typename T, typename... Ts> +void print(T first, Ts... rest) { + (void)first; + print(rest...); +} + +template<typename... Ts> +void unsupported(Ts ...values) { + auto unsup = [values] {}; // expected-error{{unexpanded function parameter pack capture is unsupported}} +} + +template<typename... Ts> +void implicit_capture(Ts ...values) { + auto implicit = [&] { print(values...); }; + implicit(); +} + +template<typename... Ts> +void do_print(Ts... values) { + auto bycopy = [values...]() { print(values...); }; + bycopy(); + auto byref = [&values...]() { print(values...); }; + byref(); + + auto bycopy2 = [=]() { print(values...); }; + bycopy2(); + auto byref2 = [&]() { print(values...); }; + byref2(); +} + +template void do_print(int, float, double); + +template<typename T, int... Values> +void bogus_expansions(T x) { + auto l1 = [x...] {}; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + auto l2 = [Values...] {}; // expected-error{{'Values' in capture list does not name a variable}} +} + +void g(int*, float*, double*); + +template<class... Args> +void std_example(Args... args) { + auto lm = [&, args...] { return g(args...); }; +}; + +template void std_example(int*, float*, double*); + +template<typename ...Args> +void variadic_lambda(Args... args) { + auto lambda = [](Args... inner_args) { return g(inner_args...); }; + lambda(args...); +} + +template void variadic_lambda(int*, float*, double*); diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp new file mode 100644 index 0000000000000..562f92a78bbcc --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void test_nonaggregate(int i) { + auto lambda = [i]() -> void {}; // expected-note 3{{candidate constructor}} + decltype(lambda) foo = { 1 }; // expected-error{{no matching constructor}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp new file mode 100644 index 0000000000000..d816e1702a6da --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void missing_lambda_declarator() { + [](){}(); +} + +template<typename T> T get(); + +void infer_void_return_type(int i) { + if (i > 17) + return []() { }(); + + if (i > 11) + return []() { return; }(); + + return [](int x) { + switch (x) { + case 0: return get<void>(); + case 1: return; + case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}} + } + }(7); +} + +struct X { }; + +X infer_X_return_type(X x) { + return [&x](int y) { // expected-warning{{omitted result type}} + if (y > 0) + return X(); + else + return x; + }(5); +} + +X infer_X_return_type_fail(X x) { + return [x](int y) { // expected-warning{{omitted result type}} + if (y > 0) + return X(); + else + return x; // expected-error{{return type 'const X' must match previous return type 'X' when lambda expression has unspecified explicit return type}} + }(5); +} + +struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} +void test_result_type(int N) { + auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}} + + typedef int vla[N]; + auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int [N]')}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm new file mode 100644 index 0000000000000..0126e23a74abb --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +@interface A +@end + +void test_result_type() { + auto l1 = [] () -> A { }; // expected-error{{non-pointer Objective-C class type 'A' in lambda expression result}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp new file mode 100644 index 0000000000000..68460f0354bc0 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -std=c++11 %s -Winvalid-noreturn -verify + +// An attribute-specifier-seq in a lambda-declarator appertains to the +// type of the corresponding function call operator. +void test_attributes() { + auto nrl = [](int x) -> int { if (x > 0) return x; }; // expected-warning{{control may reach end of non-void lambda}} + + auto nrl2 = []() [[noreturn]] { return; }; // expected-error{{lambda declared 'noreturn' should not return}} +} + +template<typename T> +struct bogus_override_if_virtual : public T { + bogus_override_if_virtual() : T(*(T*)0) { } + int operator()() const; +}; + +void test_quals() { + // This function call operator is declared const (9.3.1) if and only + // if the lambda- expression's parameter-declaration-clause is not + // followed by mutable. + auto l = [=](){}; // expected-note{{method is not marked volatile}} + const decltype(l) lc = l; + l(); + lc(); + + auto ml = [=]() mutable{}; // expected-note{{method is not marked const}} \ + // expected-note{{method is not marked volatile}} + const decltype(ml) mlc = ml; + ml(); + mlc(); // expected-error{{no matching function for call to object of type}} + + // It is neither virtual nor declared volatile. + volatile decltype(l) lv = l; + volatile decltype(ml) mlv = ml; + lv(); // expected-error{{no matching function for call to object of type}} + mlv(); // expected-error{{no matching function for call to object of type}} + + bogus_override_if_virtual<decltype(l)> bogus; +} + +// Default arguments (8.3.6) shall not be specified in the +// parameter-declaration-clause of a lambda- declarator. +// Note: Removed by core issue 974. +int test_default_args() { + return [](int i = 5, // expected-warning{{C++11 forbids default arguments for lambda expressions}} + int j = 17) { return i+j;}(5, 6); +} + +// Any exception-specification specified on a lambda-expression +// applies to the corresponding function call operator. +void test_exception_spec() { + auto tl1 = []() throw(int) {}; + auto tl2 = []() {}; + static_assert(!noexcept(tl1()), "lambda can throw"); + static_assert(!noexcept(tl2()), "lambda can throw"); + + auto ntl1 = []() throw() {}; + auto ntl2 = []() noexcept(true) {}; + auto ntl3 = []() noexcept {}; + static_assert(noexcept(ntl1()), "lambda cannot throw"); + static_assert(noexcept(ntl2()), "lambda cannot throw"); + static_assert(noexcept(ntl3()), "lambda cannot throw"); +} + diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp new file mode 100644 index 0000000000000..8b43cefa92c06 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void test_conversion() { + int (*fp1)(int) = [](int x) { return x + 1; }; + void (*fp2)(int) = [](int x) { }; + + const auto lambda = [](int x) { }; + void (*fp3)(int) = lambda; + + volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}} + void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}} +} + +void test_no_conversion() { + int (*fp1)(int) = [=](int x) { return x + 1; }; // expected-error{{no viable conversion}} + void (*fp2)(int) = [&](int x) { }; // expected-error{{no viable conversion}} +} + +void test_wonky() { + const auto l = [](int x) mutable -> int { return + 1; }; + l(17); // okay: uses conversion function +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp new file mode 100644 index 0000000000000..9dbe2e189f4af --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +// Check that analysis-based warnings work in lambda bodies. +void analysis_based_warnings() { + (void)[]() -> int { }; // expected-warning{{control reaches end of non-void lambda}} +} + +// Check that we get the right types of captured variables (the +// semantic-analysis part of p7). +int &check_const_int(int&); +float &check_const_int(const int&); + +void test_capture_constness(int i, const int ic) { + (void)[i,ic] ()->void { + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + (void)[=] ()->void { + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + (void)[i,ic] () mutable ->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[=] () mutable ->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[&i,&ic] ()->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[&] ()->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; +} + + +struct S1 { + int x, y; + S1 &operator=(int*); + int operator()(int); + void f() { + [&]()->int { + S1 &s1 = operator=(&this->x); + return operator()(this->x + y); + }(); + } +}; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp new file mode 100644 index 0000000000000..d1384f19dd146 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +class X0 { + void explicit_capture() { + int foo; + + (void)[foo, foo] () {}; // expected-error {{'foo' can appear only once}} + (void)[this, this] () {}; // expected-error {{'this' can appear only once}} + (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}} + (void)[=, &foo] () {}; + (void)[=, this] () {}; // expected-error {{'this' cannot be explicitly captured}} + (void)[&, foo] () {}; + (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}} + (void)[&, this] () {}; + } +}; + +struct S2 { + void f(int i); + void g(int i); +}; + +void S2::f(int i) { + (void)[&, i]{ }; + (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}} + (void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}} + (void)[=]{ this->g(i); }; + (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp new file mode 100644 index 0000000000000..49b9c66b1ce54 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify + +template<typename T> +void test_attributes() { + auto nrl = []() [[noreturn]] {}; // expected-error{{lambda declared 'noreturn' should not return}} +} + +template void test_attributes<int>(); // expected-note{{in instantiation of function}} + +template<typename T> +void call_with_zero() { + [](T *ptr) -> T& { return *ptr; }(0); +} + +template void call_with_zero<int>(); + +template<typename T> +T captures(T x, T y) { + auto lambda = [=, &y] () -> T { + T i = x; + return i + y; + }; + + return lambda(); +} + +struct X { + X(const X&); +}; + +X operator+(X, X); +X operator-(X, X); + +template int captures(int, int); +template X captures(X, X); + +template<typename T> +int infer_result(T x, T y) { + auto lambda = [=](bool b) { return x + y; }; + return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}} +} + +template int infer_result(int, int); +template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}} + +// Make sure that lambda's operator() can be used from templates. +template<typename F> +void accept_lambda(F f) { + f(1); +} + +template<typename T> +void pass_lambda(T x) { + accept_lambda([&x](T y) { return x + y; }); +} + +template void pass_lambda(int); + +namespace std { + class type_info; +} + +namespace p2 { + struct P { + virtual ~P(); + }; + + template<typename T> + struct Boom { + Boom(const Boom&) { + T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} + } + void tickle() const; + }; + + template<typename R, typename T> + void odr_used(R &r, Boom<T> boom) { + const std::type_info &ti + = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}} + boom.tickle(); // expected-note{{in instantiation of member function}} + return r; + }()); + } + + template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}} + + template<typename R, typename T> + void odr_used2(R &r, Boom<T> boom) { + const std::type_info &ti + = typeid([=,&r] () -> R& { + boom.tickle(); // expected-note{{in instantiation of member function}} + return r; + }()); + } + + template void odr_used2(P&, Boom<float>); +} + +namespace p5 { + struct NonConstCopy { + NonConstCopy(const NonConstCopy&) = delete; + NonConstCopy(NonConstCopy&); + }; + + template<typename T> + void double_capture(T &nc) { + [=] () mutable { + [=] () mutable { + T nc2(nc); + }(); + }(); + } + + template void double_capture(NonConstCopy&); +} + +namespace NonLocalLambdaInstantation { + template<typename T> + struct X { + static int value; + }; + + template<typename T> + int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}} + + template int X<int>::value; + template int X<float>::value; + template int X<int*>::value; // expected-note{{in instantiation of static data member }} + + template<typename T> + void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \ + // expected-note{{passing argument to parameter 'x' here}} + + void call_defaults() { + defaults<int>(); + defaults<float>(); + defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}} + } + + template<typename T> + struct X2 { + int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}} + }; + + X2<int> x2i; + X2<float> x2f; + X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}} +} diff --git a/test/CXX/expr/expr.prim/p12-0x.cpp b/test/CXX/expr/expr.prim/p12-0x.cpp deleted file mode 100644 index aec62ddd97a76..0000000000000 --- a/test/CXX/expr/expr.prim/p12-0x.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s - -struct S { - int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}} - int *m = &n; // ok - - int n = f(); // ok - int f(); -}; - -int i = sizeof(S::m); // ok -int j = sizeof(S::m + 42); // ok diff --git a/test/CXX/expr/expr.prim/p4-0x.cpp b/test/CXX/expr/expr.prim/p4-0x.cpp deleted file mode 100644 index 143ba897ae95e..0000000000000 --- a/test/CXX/expr/expr.prim/p4-0x.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s - -struct S { - S *p = this; // ok - decltype(this) q; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} \ - expected-error {{C++ requires a type specifier for all declarations}} - - int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} - int sz = sizeof(this); // ok -}; diff --git a/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp b/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp new file mode 100644 index 0000000000000..27b915e95965d --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -emit-llvm-only %s + +// this used to crash due to templ<int>'s dtor not being marked as used by the +// new expression in func() +struct non_trivial { + non_trivial() {} + ~non_trivial() {} +}; +template < typename T > class templ { + non_trivial n; +}; +void func() { + new templ<int>[1][1]; +} diff --git a/test/CXX/expr/expr.unary/expr.new/p17.cpp b/test/CXX/expr/expr.unary/expr.new/p17.cpp new file mode 100644 index 0000000000000..0d108eb6a894d --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p17.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class ctor { + ctor(); // expected-note{{implicitly declared private here}} +}; + +class dtor { + ~dtor(); // expected-note 3 {{implicitly declared private here}} +}; + +void test() { + new ctor[0]; // expected-error{{calling a private constructor of class 'ctor'}} + new dtor[0]; // expected-error{{calling a private destructor of class 'dtor'}} + new dtor[3]; // expected-error{{calling a private destructor of class 'dtor'}} + new dtor[3][3]; // expected-error{{calling a private destructor of class 'dtor'}} +} diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp new file mode 100644 index 0000000000000..2dd6b23fa0249 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify + +namespace rdar10544564 { + // Check that we don't attempt to use an overloaded operator& when + // naming a pointer-to-member. + struct X { + void** operator & (); + }; + + struct Y + { + public: + X member; + X memfunc1(); + X memfunc2(); + X memfunc2(int); + + void test() { + X Y::*data_mem_ptr = &Y::member; + X (Y::*func_mem_ptr1)() = &Y::memfunc1; + X (Y::*func_mem_ptr2)() = &Y::memfunc2; + } + }; + + X Y::*data_mem_ptr = &Y::member; + X (Y::*func_mem_ptr1)() = &Y::memfunc1; + X (Y::*func_mem_ptr2)() = &Y::memfunc2; +} diff --git a/test/CXX/lex/lex.charset/p2-cxx11.cpp b/test/CXX/lex/lex.charset/p2-cxx11.cpp new file mode 100644 index 0000000000000..b9192cebe61e9 --- /dev/null +++ b/test/CXX/lex/lex.charset/p2-cxx11.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +char c00 = '\u0000'; // ok +char c01 = '\u0001'; // ok +char c1f = '\u001f'; // ok +char c20 = '\u0020'; // ' ', ok +char c22 = '\u0022'; // ", ok +char c23 = '\u0023'; // #, ok +char c24 = '\u0024'; // $, ok +char c25 = '\u0025'; // %, ok +char c27 = '\u0027'; // ', ok +char c3f = '\u003f'; // ?, ok +char c40 = '\u0040'; // @, ok +char c41 = '\u0041'; // A, ok +char c5f = '\u005f'; // _, ok +char c60 = '\u0060'; // `, ok +char c7e = '\u007e'; // ~, ok +char c7f = '\u007f'; // ok + +wchar_t w007f = L'\u007f'; +wchar_t w0080 = L'\u0080'; +wchar_t w009f = L'\u009f'; +wchar_t w00a0 = L'\u00a0'; + +wchar_t wd799 = L'\ud799'; +wchar_t wd800 = L'\ud800'; // expected-error {{invalid universal character}} +wchar_t wdfff = L'\udfff'; // expected-error {{invalid universal character}} +wchar_t we000 = L'\ue000'; + +char32_t w10fffe = U'\U0010fffe'; +char32_t w10ffff = U'\U0010ffff'; +char32_t w110000 = U'\U00110000'; // expected-error {{invalid universal character}} + +const char *p1 = "\u0000\u0001\u001f\u0020\u0022\u0023\u0024\u0025\u0027\u003f\u0040\u0041\u005f\u0060\u007e\u007f"; +const wchar_t *p2 = L"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const char *p3 = u8"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const char16_t *p4 = u"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const char32_t *p5 = U"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const wchar_t *p6 = L"foo \U00110000 bar"; // expected-error {{invalid universal character}} +const char *p7 = u8"foo \U0000d800 bar"; // expected-error {{invalid universal character}} +const char16_t *p8 = u"foo \U0000dfff bar"; // expected-error {{invalid universal character}} +const char32_t *p9 = U"foo \U0010ffff bar"; // ok diff --git a/test/CXX/lex/lex.charset/p2-cxx98.cpp b/test/CXX/lex/lex.charset/p2-cxx98.cpp new file mode 100644 index 0000000000000..a5b7ab6488216 --- /dev/null +++ b/test/CXX/lex/lex.charset/p2-cxx98.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s + +char c00 = '\u0000'; // expected-error {{universal character name refers to a control character}} +char c01 = '\u0001'; // expected-error {{universal character name refers to a control character}} +char c1f = '\u001f'; // expected-error {{universal character name refers to a control character}} +char c20 = '\u0020'; // ' ', expected-error {{character ' ' cannot be specified by a universal character name}} +char c22 = '\u0022'; // ", expected-error {{character '"' cannot be specified by a universal character name}} +char c23 = '\u0023'; // #, expected-error {{character '#' cannot be specified by a universal character name}} +char c24 = '\u0024'; // $, ok +char c25 = '\u0025'; // %, expected-error {{character '%' cannot be specified by a universal character name}} +char c27 = '\u0027'; // ', expected-error {{character ''' cannot be specified by a universal character name}} +char c3f = '\u003f'; // ?, expected-error {{character '?' cannot be specified by a universal character name}} +char c40 = '\u0040'; // @, ok +char c41 = '\u0041'; // A, expected-error {{character 'A' cannot be specified by a universal character name}} +char c5f = '\u005f'; // _, expected-error {{character '_' cannot be specified by a universal character name}} +char c60 = '\u0060'; // `, ok +char c7e = '\u007e'; // ~, expected-error {{character '~' cannot be specified by a universal character name}} +char c7f = '\u007f'; // expected-error {{universal character name refers to a control character}} + +wchar_t w007f = L'\u007f'; // expected-error {{universal character name refers to a control character}} +wchar_t w0080 = L'\u0080'; // expected-error {{universal character name refers to a control character}} +wchar_t w009f = L'\u009f'; // expected-error {{universal character name refers to a control character}} +wchar_t w00a0 = L'\u00a0'; + +wchar_t wd799 = L'\ud799'; +wchar_t wd800 = L'\ud800'; // expected-error {{invalid universal character}} +wchar_t wdfff = L'\udfff'; // expected-error {{invalid universal character}} +wchar_t we000 = L'\ue000'; + +const char *s00 = "\u0000"; // expected-error {{universal character name refers to a control character}} +const char *s01 = "\u0001"; // expected-error {{universal character name refers to a control character}} +const char *s1f = "\u001f"; // expected-error {{universal character name refers to a control character}} +const char *s20 = "\u0020"; // ' ', expected-error {{character ' ' cannot be specified by a universal character name}} +const char *s22 = "\u0022"; // ", expected-error {{character '"' cannot be specified by a universal character name}} +const char *s23 = "\u0023"; // #, expected-error {{character '#' cannot be specified by a universal character name}} +const char *s24 = "\u0024"; // $, ok +const char *s25 = "\u0025"; // %, expected-error {{character '%' cannot be specified by a universal character name}} +const char *s27 = "\u0027"; // ', expected-error {{character ''' cannot be specified by a universal character name}} +const char *s3f = "\u003f"; // ?, expected-error {{character '?' cannot be specified by a universal character name}} +const char *s40 = "\u0040"; // @, ok +const char *s41 = "\u0041"; // A, expected-error {{character 'A' cannot be specified by a universal character name}} +const char *s5f = "\u005f"; // _, expected-error {{character '_' cannot be specified by a universal character name}} +const char *s60 = "\u0060"; // `, ok +const char *s7e = "\u007e"; // ~, expected-error {{character '~' cannot be specified by a universal character name}} +const char *s7f = "\u007f"; // expected-error {{universal character name refers to a control character}} + +const wchar_t *ws007f = L"\u007f"; // expected-error {{universal character name refers to a control character}} +const wchar_t *ws0080 = L"\u0080"; // expected-error {{universal character name refers to a control character}} +const wchar_t *ws009f = L"\u009f"; // expected-error {{universal character name refers to a control character}} +const wchar_t *ws00a0 = L"\u00a0"; + +const wchar_t *wsd799 = L"\ud799"; +const wchar_t *wsd800 = L"\ud800"; // expected-error {{invalid universal character}} +const wchar_t *wsdfff = L"\udfff"; // expected-error {{invalid universal character}} +const wchar_t *wse000 = L"\ue000"; diff --git a/test/CXX/lex/lex.literal/lex.ext/p1.cpp b/test/CXX/lex/lex.literal/lex.ext/p1.cpp index 39812280c0901..1c227a1b10d38 100644 --- a/test/CXX/lex/lex.literal/lex.ext/p1.cpp +++ b/test/CXX/lex/lex.literal/lex.ext/p1.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -int * operator "" p31(long double); // expected-warning{{user-defined literal with suffix 'p31' is preempted by C99 hexfloat extension}} -long double operator "" _p31(long double); -long double operator "" pi(long double); // expected-warning{{user-defined literals not starting with '_' are reserved by the implementation}} +void operator "" p31(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} +void operator "" _p31(long double); +long double operator "" pi(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} float hexfloat = 0x1p31; // allow hexfloats diff --git a/test/CXX/lex/lex.literal/lex.ext/p10.cpp b/test/CXX/lex/lex.literal/lex.ext/p10.cpp new file mode 100644 index 0000000000000..1b5d3880cb612 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p10.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); +void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} +void operator "" wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} + +template<typename T> +void f() { + // A program containing a reserved ud-suffix is ill-formed. + 123wibble; // expected-error {{invalid suffix 'wibble'}} + 123.0wibble; // expected-error {{invalid suffix 'wibble'}} + const char *p = ""wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}} + const char *q = R"x("hello")x"wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}} +} diff --git a/test/CXX/lex/lex.literal/lex.ext/p2.cpp b/test/CXX/lex/lex.literal/lex.ext/p2.cpp new file mode 100644 index 0000000000000..3f3f796e556d7 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p2.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +typedef decltype(sizeof(int)) size_t; + +// FIXME: These diagnostics should say 'size_t' instead of 'unsigned long' +int a = 123_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template}} +int b = 4.2_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'long double' or 'const char *', and no matching literal operator template}} +int c = "foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char *' and 'unsigned}} +int d = L"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const wchar_t *' and 'unsigned}} +int e = u8"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char *' and 'unsigned}} +int f = u"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char16_t *' and 'unsigned}} +int g = U"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char32_t *' and 'unsigned}} +int h = 'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char'}} +int i = L'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'wchar_t'}} +int j = u'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char16_t'}} +int k = U'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char32_t'}} diff --git a/test/CXX/lex/lex.literal/lex.ext/p3.cpp b/test/CXX/lex/lex.literal/lex.ext/p3.cpp new file mode 100644 index 0000000000000..43f3468e96d35 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p3.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +int &operator "" _x1 (unsigned long long); +int &i1 = 0x123_x1; + +double &operator "" _x1 (const char *); +int &i2 = 45_x1; + +template<char...> char &operator "" _x1 (); +int &i3 = 0377_x1; + +int &i4 = 90000000000000000000000000000000000000000000000_x1; // expected-warning {{integer constant is too large}} + +double &operator "" _x2 (const char *); +double &i5 = 123123123123123123123123123123123123123123123_x2; + +template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); } +static_assert(123456789012345678901234567890123456789012345678901234567890_x3 == 60, ""); diff --git a/test/CXX/lex/lex.literal/lex.ext/p4.cpp b/test/CXX/lex/lex.literal/lex.ext/p4.cpp new file mode 100644 index 0000000000000..011e832c69d72 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p4.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +int &operator "" _x1 (long double); +int &i1 = 0.123_x1; + +double &operator "" _x1 (const char *); +int &i2 = 45._x1; + +template<char...> char &operator "" _x1 (); +int &i3 = 0377e-1_x1; + +int &i4 = 1e1000000_x1; // expected-warning {{too large for type 'long double'}} + +double &operator "" _x2 (const char *); +double &i5 = 1e1000000_x2; + +template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); } +static_assert(1e1000000_x3 == 9, ""); diff --git a/test/CXX/lex/lex.literal/lex.ext/p5.cpp b/test/CXX/lex/lex.literal/lex.ext/p5.cpp new file mode 100644 index 0000000000000..4655aa17dc222 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p5.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); + +int &operator "" _x1 (const char *); +double &operator "" _x1 (const char *, size_t); +double &i1 = "foo"_x1; +double &i2 = u8"foo"_x1; +double &i3 = L"foo"_x1; // expected-error {{no matching literal operator}} + +char &operator "" _x1(const wchar_t *, size_t); +char &i4 = L"foo"_x1; // ok +double &i5 = R"(foo)"_x1; // ok diff --git a/test/CXX/lex/lex.literal/lex.ext/p6.cpp b/test/CXX/lex/lex.literal/lex.ext/p6.cpp new file mode 100644 index 0000000000000..23cd7081d5e3e --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p6.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); + +int &operator "" _x1 (const char *); +double &i1 = 'a'_x1; // expected-error {{no matching literal operator}} +double &operator "" _x1 (wchar_t); +double &i2 = L'a'_x1; +double &i3 = 'a'_x1; // expected-error {{no matching literal operator}} +double &i4 = operator"" _x1('a'); // ok + +char &operator "" _x1(char16_t); +char &i5 = u'a'_x1; // ok +double &i6 = L'a'_x1; // ok diff --git a/test/CXX/lex/lex.literal/lex.ext/p7.cpp b/test/CXX/lex/lex.literal/lex.ext/p7.cpp new file mode 100644 index 0000000000000..79c9394a96ba3 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p7.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); +namespace std { + struct string {}; +} + +template<typename T, typename U> struct same_type; +template<typename T> struct same_type<T, T> {}; + +namespace std_example { + +long double operator "" _w(long double); +std::string operator "" _w(const char16_t*, size_t); +unsigned operator "" _w(const char*); +int main() { + auto v1 = 1.2_w; // calls operator "" _w(1.2L) + auto v2 = u"one"_w; // calls operator "" _w(u"one", 3) + auto v3 = 12_w; // calls operator "" _w("12") + "two"_w; // expected-error {{no matching literal operator}} + + same_type<decltype(v1), long double> test1; + same_type<decltype(v2), std::string> test2; + same_type<decltype(v3), unsigned> test3; +} + +} diff --git a/test/CXX/lex/lex.literal/lex.ext/p8.cpp b/test/CXX/lex/lex.literal/lex.ext/p8.cpp new file mode 100644 index 0000000000000..d9078221ff5e3 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p8.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); +constexpr const char *operator "" _id(const char *p, size_t) { return p; } +constexpr const char *s = "foo"_id "bar" "baz"_id "quux"; + +constexpr bool streq(const char *p, const char *q) { + return *p == *q && (!*p || streq(p+1, q+1)); +} +static_assert(streq(s, "foobarbazquux"), ""); + +constexpr const char *operator "" _trim(const char *p, size_t n) { + return *p == ' ' ? operator "" _trim(p + 1, n - 1) : p; +} +constexpr const char *t = " " " "_trim " foo"; +static_assert(streq(t, "foo"), ""); + +const char *u = "foo" "bar"_id "baz" "quux"_di "corge"; // expected-error {{differing user-defined suffixes ('_id' and '_di') in string literal concatenation}} diff --git a/test/CXX/lex/lex.literal/lex.ext/p9.cpp b/test/CXX/lex/lex.literal/lex.ext/p9.cpp new file mode 100644 index 0000000000000..65e27b41b0668 --- /dev/null +++ b/test/CXX/lex/lex.literal/lex.ext/p9.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +using size_t = decltype(sizeof(int)); +void operator "" _x(const wchar_t *, size_t); + +namespace std_example { + +int main() { + L"A" "B" "C"_x; + "P"_x "Q" "R"_y; // expected-error {{differing user-defined suffixes ('_x' and '_y') in string literal concatenation}} +} + +} diff --git a/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.list/p6.cpp b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.list/p6.cpp new file mode 100644 index 0000000000000..ea059cef7c803 --- /dev/null +++ b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.list/p6.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// rdar://problem/11120365 +namespace test0 { + template <class T> struct A { + static void foo(const T &t) {} + static void foo(T &&t) { + t.foo(); // expected-error {{member reference base type 'int' is not a structure or union}} + } + }; + + void test() { + A<int>::foo({}); // expected-note {{requested here}} + } +} diff --git a/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp b/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp new file mode 100644 index 0000000000000..31a679f1ebc0b --- /dev/null +++ b/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify + +namespace ExplicitConv { + struct X { }; // expected-note 2{{candidate constructor}} + + struct Y { + explicit operator X() const; + }; + + void test(const Y& y) { + X x(static_cast<X>(y)); + X x2((X)y); + X x3 = y; // expected-error{{no viable conversion from 'const ExplicitConv::Y' to 'ExplicitConv::X'}} + } +} + +namespace DR899 { + struct C { }; // expected-note 2 {{candidate constructor}} + + struct A { + explicit operator int() const; + explicit operator C() const; + }; + + struct B { + int i; + B(const A& a): i(a) { } + }; + + int main() { + A a; + int i = a; // expected-error{{no viable conversion}} + int j(a); + C c = a; // expected-error{{no viable conversion}} + C c2(a); + } +} diff --git a/test/CXX/over/over.oper/over.literal/p2.cpp b/test/CXX/over/over.oper/over.literal/p2.cpp new file mode 100644 index 0000000000000..c012104314b26 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p2.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +void operator "" _a(const char *); + +namespace N { + using ::operator "" _a; + + void operator "" _b(const char *); +} + +using N::operator "" _b; + +class C { + void operator "" _c(const char *); // expected-error {{must be in a namespace or global scope}} + + static void operator "" _c(unsigned long long); // expected-error {{must be in a namespace or global scope}} + + friend void operator "" _d(const char *); +}; + +int operator "" _e; // expected-error {{cannot be the name of a variable}} + +void f() { + int operator "" _f; // expected-error {{cannot be the name of a variable}} +} + +extern "C++" { + void operator "" _g(const char *); +} + +template<char...> void operator "" _h() {} + +template<> void operator "" _h<'a', 'b', 'c'>() {} + +template void operator "" _h<'a', 'b', 'c', 'd'>(); diff --git a/test/CXX/over/over.oper/over.literal/p3.cpp b/test/CXX/over/over.oper/over.literal/p3.cpp new file mode 100644 index 0000000000000..674ace9aee192 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p3.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +using size_t = decltype(sizeof(int)); + +// Acceptable parameter declarations +char operator "" _a(const char *); +char operator "" _a(const char []); +char operator "" _a(unsigned long long); +char operator "" _a(long double); +char operator "" _a(char); +char operator "" _a(const volatile char); +char operator "" _a(wchar_t); +char operator "" _a(char16_t); +char operator "" _a(char32_t); +char operator "" _a(const char *, size_t); +char operator "" _a(const wchar_t *, size_t); +char operator "" _a(const char16_t *, size_t); +char operator "" _a(const char32_t *, size_t); +char operator "" _a(const char [32], size_t); + +// Unacceptable parameter declarations +char operator "" _b(); // expected-error {{parameter}} +char operator "" _b(const wchar_t *); // expected-error {{parameter}} +char operator "" _b(long long); // expected-error {{parameter}} +char operator "" _b(double); // expected-error {{parameter}} +char operator "" _b(short); // expected-error {{parameter}} +char operator "" _a(char, int = 0); // expected-error {{parameter}} +char operator "" _b(unsigned short); // expected-error {{parameter}} +char operator "" _b(signed char); // expected-error {{parameter}} +char operator "" _b(unsigned char); // expected-error {{parameter}} +char operator "" _b(const short *, size_t); // expected-error {{parameter}} +char operator "" _b(const unsigned short *, size_t); // expected-error {{parameter}} +char operator "" _b(const signed char *, size_t); // expected-error {{parameter}} +char operator "" _b(const unsigned char *, size_t); // expected-error {{parameter}} +char operator "" _a(const volatile char *, size_t); // expected-error {{parameter}} +char operator "" _a(volatile wchar_t *, size_t); // expected-error {{parameter}} +char operator "" _a(char16_t *, size_t); // expected-error {{parameter}} +char operator "" _a(const char32_t *, size_t, bool = false); // expected-error {{parameter}} +char operator "" _a(const char *, signed long); // expected-error {{parameter}} +char operator "" _a(const char *, size_t = 0); // expected-error {{default argument}} diff --git a/test/CXX/over/over.oper/over.literal/p5.cpp b/test/CXX/over/over.oper/over.literal/p5.cpp new file mode 100644 index 0000000000000..66f3f97eaac37 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p5.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +using size_t = decltype(sizeof(int)); +template<char...> struct S {}; + +template<char...> void operator "" _a(); +template<char... C> S<C...> operator "" _a(); + +template<typename T> struct U { + friend int operator "" _a(const char *, size_t); + // FIXME: It's not entirely clear whether this is intended to be legal. + friend U operator "" _a(const T *, size_t); // expected-error {{parameter}} +}; +template<char...> struct V { + friend void operator "" _b(); // expected-error {{parameter}} +}; + +template<char... C, int N = 0> void operator "" _b(); // expected-error {{parameter}} +template<char... C> void operator "" _b(int N = 0); // expected-error {{parameter}} +template<char, char...> void operator "" _b(); // expected-error {{parameter}} +template<typename T> T operator "" _b(const char *); // expected-error {{parameter}} +template<typename T> int operator "" _b(const T *, size_t); // expected-error {{parameter}} diff --git a/test/CXX/over/over.oper/over.literal/p6.cpp b/test/CXX/over/over.oper/over.literal/p6.cpp new file mode 100644 index 0000000000000..6bfb8560d6889 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p6.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +extern "C" void operator "" _a(const char *); // expected-error {{must have C++ linkage}} +extern "C" template<char...> void operator "" _b(); // expected-error {{must have C++ linkage}} + +extern "C" { + void operator "" _c(const char *); // expected-error {{must have C++ linkage}} + template<char...> void operator "" _d(); // expected-error {{must have C++ linkage}} + namespace N { + void operator "" _e(const char *); // expected-error {{must have C++ linkage}} + template<char...> void operator "" _f(); // expected-error {{must have C++ linkage}} + } +} diff --git a/test/CXX/over/over.oper/over.literal/p7.cpp b/test/CXX/over/over.oper/over.literal/p7.cpp new file mode 100644 index 0000000000000..72411b954e142 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p7.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +constexpr int operator "" _a(const char *c) { + return c[0]; +} + +static_assert(operator "" _a("foo") == 'f', ""); + +void puts(const char *); +static inline void operator "" _puts(const char *c) { + puts(c); +} +void f() { + operator "" _puts("foo"); + operator "" _puts("bar"); +} diff --git a/test/CXX/over/over.oper/over.literal/p8.cpp b/test/CXX/over/over.oper/over.literal/p8.cpp new file mode 100644 index 0000000000000..3f76082d10a97 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p8.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +struct string; +namespace std { + using size_t = decltype(sizeof(int)); +} + +void operator "" _km(long double); // ok +string operator "" _i18n(const char*, std::size_t); // ok +// FIXME: This should be accepted once we support UCNs +template<char...> int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-error {{expected identifier}} +float operator ""E(const char *); // expected-error {{C++11 requires a space between literal and identifier}} expected-warning {{reserved}} +float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}} +string operator "" 5X(const char *, std::size_t); // expected-error {{expected identifier}} +double operator "" _miles(double); // expected-error {{parameter}} +template<char...> int operator "" j(const char*); // expected-error {{parameter}} + +// FIXME: Accept this as an extension, with a fix-it to add the space +float operator ""_E(const char *); // expected-error {{C++11 requires a space between the "" and the user-defined suffix in a literal operator}} diff --git a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp index d2a23ce96df26..e0217112d91b5 100644 --- a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp +++ b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-bool-conversion %s typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t; @@ -100,8 +100,8 @@ int main() { (void) reinterpret_cast<int>(two); } //expected-error {{reinterpret_cast}} { (void) reinterpret_cast<int (*)(char, double)>(two); } //expected-error {{reinterpret_cast}} - { bool b = (twoT<int>); } // ok - { bool b = (twoT<int, int>); } //ok + { bool b = (twoT<int>); } + { bool b = (twoT<int, int>); } { bool b = &twoT<int>; //&foo<int>; } b = &(twoT<int>); } @@ -116,7 +116,7 @@ int main() { ptrdiff_t x = (ptrdiff_t) &twoT<int,int>; x = (ptrdiff_t) &twoT<int>; } - { oneT<int>; &oneT<int>; } //expected-warning 2{{ expression result unused }} + { oneT<int>; &oneT<int>; } //expected-warning 2{{expression result unused}} { static_cast<void>(cant_resolve<int>); } // expected-error {{address of overload}} { bool b = cant_resolve<int>; } // expected-error {{address of overload}} { (void) cant_resolve<int>; } // expected-error {{address of overload}} @@ -165,8 +165,8 @@ namespace member_pointers { { bool b = &S::f<char>; } { bool b = &S::f<int>; } // These next two errors are terrible. - { bool b = s.f<char>; } // expected-error {{cannot initialize}} - { bool b = s.f<int>; } // expected-error {{cannot initialize}} + { bool b = s.f<char>; } // expected-error {{reference to non-static member function must be called}} + { bool b = s.f<int>; } // expected-error {{reference to non-static member function must be called}} { bool b = &s.f<char>; } // expected-error {{cannot create a non-constant pointer to member function}} { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}} diff --git a/test/CXX/special/class.copy/implicit-move-def.cpp b/test/CXX/special/class.copy/implicit-move-def.cpp index 94023cbc1d7be..5c54aea124430 100644 --- a/test/CXX/special/class.copy/implicit-move-def.cpp +++ b/test/CXX/special/class.copy/implicit-move-def.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-ASSIGN %s +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-ASSIGN %s // RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-CTOR %s // construct @@ -96,21 +97,21 @@ void move_VirtualWithEmptyBase(VirtualWithEmptyBase &x, VirtualWithEmptyBase &y) // CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN20VirtualWithEmptyBaseaSEOS_ // CHECK-ASSIGN: store // CHECK-ASSIGN-NEXT: store -// CHECK-NOT: call -// CHECK: ret +// CHECK-ASSIGN-NOT: call +// CHECK-ASSIGN: ret // CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN1CaSEOS_ // CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ // move ctors -// CHECK-CTOR: define linkonce_odr void @_ZN1HC2EOS_ -// CHECK-CTOR: call void @_ZN1GC2EOS_ -// CHECK-CTOR: call void @_ZN1FC1EOS_ -// CHECK-CTOR: call void @_ZN1EC1EOS_ +// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1HC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1GC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ // array loop // CHECK-CTOR: br i1 -// CHECK-CTOR: call void @_ZN1FC1EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ -// CHECK-CTOR: define linkonce_odr void @_ZN1GC2EOS_ -// CHECK-CTOR: call void @_ZN1EC1EOS_ +// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1GC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp index 74f7eee9ee898..b1b298e893ff2 100644 --- a/test/CXX/special/class.copy/implicit-move.cpp +++ b/test/CXX/special/class.copy/implicit-move.cpp @@ -25,10 +25,10 @@ struct HasCopyAssignment { HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false); }; -struct HasMoveConstructor { // expected-note {{implicit copy assignment}} +struct HasMoveConstructor { ThrowingCopy tc; HasMoveConstructor() noexcept; - HasMoveConstructor(HasMoveConstructor &&) noexcept; + HasMoveConstructor(HasMoveConstructor &&) noexcept; // expected-note {{copy assignment operator is implicitly deleted because 'HasMoveConstructor' has a user-declared move constructor}} }; struct HasMoveAssignment { // expected-note {{implicit copy constructor}} @@ -54,7 +54,7 @@ void test_basic_exclusion() { static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), ""); HasMoveConstructor hmc; - hmc = HasMoveConstructor(); // expected-error {{selected deleted operator}} + hmc = HasMoveConstructor(); // expected-error {{selected implicitly-deleted copy assignment}} (HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}} HasMoveAssignment hma; @@ -87,9 +87,9 @@ private: ~PrivateDestructor() noexcept; }; -struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note {{explicitly marked deleted}} -struct ContainsPrivateDestructor { // expected-note {{explicitly marked deleted}} - PrivateDestructor pd; +struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}} +struct ContainsPrivateDestructor { + PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}} }; struct NonTrivialCopyOnly { @@ -131,8 +131,8 @@ void test_deletion_exclusion() { ContainsPrivateMove cpm; static_assert(!noexcept(cpm = ContainsPrivateMove()), ""); - (InheritsPrivateDestructor(InheritsPrivateDestructor())); // expected-error {{call to deleted constructor}} - (ContainsPrivateDestructor(ContainsPrivateDestructor())); // expected-error {{call to deleted constructor}} + (InheritsPrivateDestructor(InheritsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} + (ContainsPrivateDestructor(ContainsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} static_assert(!noexcept(InheritsNonTrivialCopyOnly(InheritsNonTrivialCopyOnly())), ""); static_assert(!noexcept(ContainsNonTrivialCopyOnly(ContainsNonTrivialCopyOnly())), ""); @@ -162,3 +162,75 @@ struct ContainsRValueRef { void test_contains_rref() { (ContainsRValueRef(ContainsRValueRef())); } + + +namespace DR1402 { + struct NonTrivialCopyCtor { + NonTrivialCopyCtor(const NonTrivialCopyCtor &); + }; + struct NonTrivialCopyAssign { + NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &); + }; + + struct NonTrivialCopyCtorVBase : virtual NonTrivialCopyCtor { + NonTrivialCopyCtorVBase(NonTrivialCopyCtorVBase &&); + NonTrivialCopyCtorVBase &operator=(NonTrivialCopyCtorVBase &&) = default; + }; + struct NonTrivialCopyAssignVBase : virtual NonTrivialCopyAssign { + NonTrivialCopyAssignVBase(NonTrivialCopyAssignVBase &&); + NonTrivialCopyAssignVBase &operator=(NonTrivialCopyAssignVBase &&) = default; + }; + + struct NonTrivialMoveAssign { + NonTrivialMoveAssign(NonTrivialMoveAssign&&); + NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&); + }; + struct NonTrivialMoveAssignVBase : virtual NonTrivialMoveAssign { + NonTrivialMoveAssignVBase(NonTrivialMoveAssignVBase &&); + NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default; + }; + + // A non-movable, non-trivially-copyable class type as a subobject inhibits + // the declaration of a move operation. + struct NoMove1 { NonTrivialCopyCtor ntcc; }; // expected-note 2{{'const DR1402::NoMove1 &'}} + struct NoMove2 { NonTrivialCopyAssign ntcc; }; // expected-note 2{{'const DR1402::NoMove2 &'}} + struct NoMove3 : NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove3 &'}} + struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove4 &'}} + struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove5 &'}} + struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove6 &'}} + struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'DR1402::NoMove7 &'}} + struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'DR1402::NoMove8 &'}} + + // A non-trivially-move-assignable virtual base class inhibits the declaration + // of a move assignment (which might move-assign the base class multiple + // times). + struct NoMove9 : NonTrivialMoveAssign {}; + struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'DR1402::NoMove10 &'}} + struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'DR1402::NoMove11 &'}} + + struct Test { + friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{no matching function}} + friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{no matching function}} + friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{no matching function}} + friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{no matching function}} + friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{no matching function}} + friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{no matching function}} + friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{no matching function}} + friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{no matching function}} + friend NoMove9::NoMove9(NoMove9 &&); + friend NoMove10::NoMove10(NoMove10 &&); + friend NoMove11::NoMove11(NoMove11 &&); + + friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{no matching function}} + friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{no matching function}} + friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{no matching function}} + friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{no matching function}} + friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{no matching function}} + friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{no matching function}} + friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{no matching function}} + friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{no matching function}} + friend NoMove9 &NoMove9::operator=(NoMove9 &&); + friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{no matching function}} + friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{no matching function}} + }; +} diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp index 752872adb9f5d..b2b4f6a87f7cd 100644 --- a/test/CXX/special/class.copy/p11.0x.copy.cpp +++ b/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -4,22 +4,28 @@ struct NonTrivial { NonTrivial(const NonTrivial&); }; -union DeletedNTVariant { // expected-note{{here}} - NonTrivial NT; +// A defaulted copy constructor for a class X is defined as deleted if X has: + +// -- a variant member with a non-trivial corresponding constructor +union DeletedNTVariant { + NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} DeletedNTVariant(); }; DeletedNTVariant DVa; -DeletedNTVariant DVb(DVa); // expected-error{{call to deleted constructor}} +DeletedNTVariant DVb(DVa); // expected-error{{call to implicitly-deleted copy constructor}} -struct DeletedNTVariant2 { // expected-note{{here}} +struct DeletedNTVariant2 { union { - NonTrivial NT; + NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant2' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} }; DeletedNTVariant2(); }; DeletedNTVariant2 DV2a; -DeletedNTVariant2 DV2b(DV2a); // expected-error{{call to deleted constructor}} +DeletedNTVariant2 DV2b(DV2a); // expected-error{{call to implicitly-deleted copy constructor}} +// -- a non-static data member of class type M (or array thereof) that cannot be +// copied because overload resolution results in an ambiguity or a function +// that is deleted or inaccessible struct NoAccess { NoAccess() = default; private: @@ -28,11 +34,11 @@ private: friend struct HasAccess; }; -struct HasNoAccess { // expected-note{{here}} - NoAccess NA; +struct HasNoAccess { + NoAccess NA; // expected-note{{copy constructor of 'HasNoAccess' is implicitly deleted because field 'NA' has an inaccessible copy constructor}} }; HasNoAccess HNAa; -HasNoAccess HNAb(HNAa); // expected-error{{call to deleted constructor}} +HasNoAccess HNAb(HNAa); // expected-error{{call to implicitly-deleted copy constructor}} struct HasAccess { NoAccess NA; @@ -49,33 +55,52 @@ struct Ambiguity { Ambiguity(volatile Ambiguity&); }; -struct IsAmbiguous { // expected-note{{here}} +struct IsAmbiguous { NonConst NC; - Ambiguity A; + Ambiguity A; // expected-note 2{{copy constructor of 'IsAmbiguous' is implicitly deleted because field 'A' has multiple copy constructors}} IsAmbiguous(); }; IsAmbiguous IAa; -IsAmbiguous IAb(IAa); // expected-error{{call to deleted constructor}} +IsAmbiguous IAb(IAa); // expected-error{{call to implicitly-deleted copy constructor}} -struct Deleted { // expected-note{{here}} - IsAmbiguous IA; +struct Deleted { + IsAmbiguous IA; // expected-note{{copy constructor of 'Deleted' is implicitly deleted because field 'IA' has a deleted copy constructor}} }; Deleted Da; -Deleted Db(Da); // expected-error{{call to deleted constructor}} +Deleted Db(Da); // expected-error{{call to implicitly-deleted copy constructor}} + +// -- a direct or virtual base class B that cannot be copied because overload +// resolution results in an ambiguity or a function that is deleted or +// inaccessible +struct AmbiguousCopyBase : Ambiguity { // expected-note 2{{copy constructor of 'AmbiguousCopyBase' is implicitly deleted because base class 'Ambiguity' has multiple copy constructors}} + NonConst NC; +}; +extern AmbiguousCopyBase ACBa; +AmbiguousCopyBase ACBb(ACBa); // expected-error {{deleted copy constructor}} +struct DeletedCopyBase : AmbiguousCopyBase {}; // expected-note {{copy constructor of 'DeletedCopyBase' is implicitly deleted because base class 'AmbiguousCopyBase' has a deleted copy constructor}} +extern DeletedCopyBase DCBa; +DeletedCopyBase DCBb(DCBa); // expected-error {{deleted copy constructor}} + +struct InaccessibleCopyBase : NoAccess {}; // expected-note {{copy constructor of 'InaccessibleCopyBase' is implicitly deleted because base class 'NoAccess' has an inaccessible copy constructor}} +extern InaccessibleCopyBase ICBa; +InaccessibleCopyBase ICBb(ICBa); // expected-error {{deleted copy constructor}} + +// -- any direct or virtual base class or non-static data member of a type with +// a destructor that is deleted or inaccessible struct NoAccessDtor { private: ~NoAccessDtor(); friend struct HasAccessDtor; }; -struct HasNoAccessDtor { // expected-note{{here}} - NoAccessDtor NAD; +struct HasNoAccessDtor { + NoAccessDtor NAD; // expected-note{{copy constructor of 'HasNoAccessDtor' is implicitly deleted because field 'NAD' has an inaccessible destructor}} HasNoAccessDtor(); ~HasNoAccessDtor(); }; HasNoAccessDtor HNADa; -HasNoAccessDtor HNADb(HNADa); // expected-error{{call to deleted constructor}} +HasNoAccessDtor HNADb(HNADa); // expected-error{{call to implicitly-deleted copy constructor}} struct HasAccessDtor { NoAccessDtor NAD; @@ -83,8 +108,14 @@ struct HasAccessDtor { HasAccessDtor HADa; HasAccessDtor HADb(HADa); -struct RValue { // expected-note{{here}} - int && ri = 1; +struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has an inaccessible destructor}} +}; +extern HasNoAccessDtorBase HNADBa; +HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}} + +// -- a non-static data member of rvalue reference type +struct RValue { + int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}} }; RValue RVa; -RValue RVb(RVa); // expected-error{{call to deleted constructor}} +RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}} diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp index 402bc31d5eec9..ff9478be8b493 100644 --- a/test/CXX/special/class.copy/p11.0x.move.cpp +++ b/test/CXX/special/class.copy/p11.0x.move.cpp @@ -4,6 +4,9 @@ struct NonTrivial { NonTrivial(NonTrivial&&); }; +// A defaulted move constructor for a class X is defined as deleted if X has: + +// -- a variant member with a non-trivial corresponding constructor union DeletedNTVariant { NonTrivial NT; DeletedNTVariant(DeletedNTVariant&&); @@ -18,6 +21,9 @@ struct DeletedNTVariant2 { }; DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}} +// -- a non-static data member of class type M (or array thereof) that cannot be +// copied because overload resolution results in an ambiguity or a function +// that is deleted or inaccessible struct NoAccess { NoAccess() = default; private: @@ -38,8 +44,45 @@ struct HasAccess { }; HasAccess::HasAccess(HasAccess&&) = default; +struct Ambiguity { + Ambiguity(const Ambiguity&&); + Ambiguity(volatile Ambiguity&&); +}; + +struct IsAmbiguous { + Ambiguity A; + IsAmbiguous(IsAmbiguous&&); +}; +IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}} + +struct Deleted { + IsAmbiguous IA; + Deleted(Deleted&&); +}; +Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}} + +// -- a direct or virtual base class B that cannot be moved because overload +// resolution results in an ambiguity or a function that is deleted or +// inaccessible +struct AmbiguousMoveBase : Ambiguity { + AmbiguousMoveBase(AmbiguousMoveBase&&); +}; +AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}} + +struct DeletedMoveBase : AmbiguousMoveBase { + DeletedMoveBase(DeletedMoveBase&&); +}; +DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}} + +struct InaccessibleMoveBase : NoAccess { + InaccessibleMoveBase(InaccessibleMoveBase&&); +}; +InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}} + +// -- any direct or virtual base class or non-static data member of a type with +// a destructor that is deleted or inaccessible struct NoAccessDtor { - NoAccessDtor(NoAccessDtor&&); + NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}} private: ~NoAccessDtor(); friend struct HasAccessDtor; @@ -57,12 +100,21 @@ struct HasAccessDtor { }; HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default; +struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}} +}; +extern HasNoAccessDtorBase HNADBa; +HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}} + +// The restriction on rvalue reference members applies to only the copy +// constructor. struct RValue { int &&ri = 1; RValue(RValue&&); }; RValue::RValue(RValue&&) = default; +// -- a non-static data member or direct or virtual base class with a type that +// does not have a move constructor and is not trivially copyable struct CopyOnly { CopyOnly(const CopyOnly&); }; @@ -71,7 +123,7 @@ struct NonMove { CopyOnly CO; NonMove(NonMove&&); }; -NonMove::NonMove(NonMove&&) = default; // expected-error{{would delete}} +NonMove::NonMove(NonMove&&) = default; // ok under DR1402 struct Moveable { Moveable(); @@ -83,3 +135,30 @@ struct HasMove { HasMove(HasMove&&); }; HasMove::HasMove(HasMove&&) = default; + +namespace DR1402 { + struct member { + member(); + member(const member&); + member& operator=(const member&); + ~member(); + }; + + struct A { + member m_; + + A() = default; + A(const A&) = default; + A& operator=(const A&) = default; + A(A&&) = default; + A& operator=(A&&) = default; + ~A() = default; + }; + + // ok, A's explicitly-defaulted move operations copy m_. + void f() { + A a, b(a), c(static_cast<A&&>(a)); + a = b; + b = static_cast<A&&>(c); + } +} diff --git a/test/CXX/special/class.copy/p13-0x.cpp b/test/CXX/special/class.copy/p13-0x.cpp new file mode 100644 index 0000000000000..0a9aa6214594f --- /dev/null +++ b/test/CXX/special/class.copy/p13-0x.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If the implicitly-defined constructor would satisfy the requirements of a +// constexpr constructor, the implicitly-defined constructor is constexpr. +struct Constexpr1 { + constexpr Constexpr1() : n(0) {} + int n; +}; +constexpr Constexpr1 c1a = Constexpr1(Constexpr1()); // ok +constexpr Constexpr1 c1b = Constexpr1(Constexpr1(c1a)); // ok + +struct Constexpr2 { + Constexpr1 ce1; + constexpr Constexpr2() = default; + constexpr Constexpr2(const Constexpr2 &o) : ce1(o.ce1) {} + // no move constructor +}; + +constexpr Constexpr2 c2a = Constexpr2(Constexpr2()); // ok +constexpr Constexpr2 c2b = Constexpr2(Constexpr2(c2a)); // ok + +struct Constexpr3 { + Constexpr2 ce2; + // all special constructors are constexpr, move ctor calls ce2's copy ctor +}; + +constexpr Constexpr3 c3a = Constexpr3(Constexpr3()); // ok +constexpr Constexpr3 c3b = Constexpr3(Constexpr3(c3a)); // ok + +struct NonConstexprCopy { + constexpr NonConstexprCopy() = default; + NonConstexprCopy(const NonConstexprCopy &); + constexpr NonConstexprCopy(NonConstexprCopy &&) = default; + + int n = 42; +}; + +NonConstexprCopy::NonConstexprCopy(const NonConstexprCopy &) = default; // expected-note {{here}} + +constexpr NonConstexprCopy ncc1 = NonConstexprCopy(NonConstexprCopy()); // ok +constexpr NonConstexprCopy ncc2 = ncc1; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct NonConstexprDefault { + NonConstexprDefault() = default; + constexpr NonConstexprDefault(int n) : n(n) {} + int n; +}; +struct Constexpr4 { + NonConstexprDefault ncd; +}; + +constexpr NonConstexprDefault ncd = NonConstexprDefault(NonConstexprDefault(1)); +constexpr Constexpr4 c4a = { ncd }; +constexpr Constexpr4 c4b = Constexpr4(c4a); +constexpr Constexpr4 c4c = Constexpr4(static_cast<Constexpr4&&>(const_cast<Constexpr4&>(c4b))); + +struct Constexpr5Base {}; +struct Constexpr5 : Constexpr5Base { constexpr Constexpr5() {} }; +constexpr Constexpr5 ce5move = Constexpr5(); +constexpr Constexpr5 ce5copy = ce5move; diff --git a/test/CXX/special/class.copy/p15-0x.cpp b/test/CXX/special/class.copy/p15-0x.cpp index 32b2714fd7028..fff88442555c0 100644 --- a/test/CXX/special/class.copy/p15-0x.cpp +++ b/test/CXX/special/class.copy/p15-0x.cpp @@ -16,3 +16,26 @@ namespace PR10622 { bar obj2(obj); } } + +namespace PR11418 { + template<typename T> + T may_throw() { + return T(); + } + + template<typename T> T &&declval() noexcept; + + struct NonPOD { + NonPOD(); + NonPOD(const NonPOD &) noexcept; + NonPOD(NonPOD &&) noexcept; + }; + + struct X { + NonPOD np = may_throw<NonPOD>(); + }; + + static_assert(noexcept(declval<X>()), "noexcept isn't working at all"); + static_assert(noexcept(X(declval<X&>())), "copy constructor can't throw"); + static_assert(noexcept(X(declval<X>())), "move constructor can't throw"); +} diff --git a/test/CXX/special/class.copy/p15-inclass.cpp b/test/CXX/special/class.copy/p15-inclass.cpp new file mode 100644 index 0000000000000..c4f8eafd937c8 --- /dev/null +++ b/test/CXX/special/class.copy/p15-inclass.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s + +namespace PR11418 { + struct NonPOD { + NonPOD(); + NonPOD(const NonPOD &); + NonPOD(NonPOD &&); + }; + + struct X { + NonPOD np; + int a = 17; + }; + + void check_copy(X x) { + X x2(x); + } + + void check_move(X x) { + X x3(static_cast<X&&>(x)); + } + + // CHECK: define linkonce_odr void @_ZN7PR114181XC2EOS0_ + // CHECK-NOT: 17 + // CHECK: call void @_ZN7PR114186NonPODC1EOS0_ + // CHECK-NOT: 17 + // CHECK: load i32* + // CHECK-NOT: 17 + // CHECK: store i32 + // CHECK-NOT: 17 + // CHECK: ret + + // CHECK: define linkonce_odr void @_ZN7PR114181XC2ERKS0_ + // CHECK-NOT: 17 + // CHECK: call void @_ZN7PR114186NonPODC1ERKS0_ + // CHECK-NOT: 17 + // CHECK: load i32* + // CHECK-NOT: 17 + // CHECK: store i32 + // CHECK-NOT: 17 + // CHECK: ret +} diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp index de2dea5be16b1..694ab5b175357 100644 --- a/test/CXX/special/class.ctor/p5-0x.cpp +++ b/test/CXX/special/class.ctor/p5-0x.cpp @@ -2,9 +2,9 @@ struct DefaultedDefCtor1 {}; struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; }; -struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; +struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; // expected-note {{explicitly marked deleted here}} class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); }; -struct DeletedDtor { ~DeletedDtor() = delete; }; +struct DeletedDtor { ~DeletedDtor() = delete; }; // expected-note 4{{explicitly marked deleted here}} class PrivateDtor { ~PrivateDtor() = default; }; class Friend { Friend() = default; ~Friend() = default; @@ -21,37 +21,42 @@ int n; // - X is a union-like class that has a variant member with a non-trivial // default constructor, -union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{deleted here}} -Deleted1a d1a; // expected-error {{deleted constructor}} +union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{default constructor of union 'Deleted1a' is implicitly deleted because field 'u' has a non-trivial default constructor}} +Deleted1a d1a; // expected-error {{implicitly-deleted default constructor}} union NotDeleted1a { DefaultedDefCtor1 nu; }; NotDeleted1a nd1a; -// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's -// default constructor is non-trivial. -union NotDeleted1b { DefaultedDefCtor2 nu; }; // unexpected-note {{deleted here}} -NotDeleted1b nd1b; // unexpected-error {{deleted constructor}} +union NotDeleted1b { DefaultedDefCtor2 nu; }; +NotDeleted1b nd1b; // - any non-static data member with no brace-or-equal-initializer is of // reference type, -class Deleted2a { Deleted2a() = default; int &a; }; // expected-note {{deleted here}} -Deleted2a d2a; // expected-error {{deleted constructor}} +class Deleted2a { + Deleted2a() = default; // expected-note 4{{implicitly deleted here}} + int &a; // expected-note 4{{because field 'a' of reference type 'int &' would not be initialized}} +}; +Deleted2a d2a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted2b { + int &&b; // expected-note {{default constructor of 'Deleted2b' is implicitly deleted because field 'b' of reference type 'int &&' would not be initialized}} +}; +Deleted2b d2b; // expected-error {{deleted default constructor}} class NotDeleted2a { int &a = n; }; NotDeleted2a nd2a; class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}} NotDeleted2b nd2b; +class NotDeleted2c { int &&a = 0; }; +NotDeleted2c nd2c; // - any non-variant non-static data member of const qualified type (or array // thereof) with no brace-or-equal-initializer does not have a user-provided // default constructor, -class Deleted3a { const int a; }; // expected-note {{here}} \ +class Deleted3a { const int a; }; // expected-note {{because field 'a' of const-qualified type 'const int' would not be initialized}} \ expected-warning {{does not declare any constructor}} \ expected-note {{will never be initialized}} -Deleted3a d3a; // expected-error {{deleted constructor}} -class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{here}} -Deleted3b d3b; // expected-error {{deleted constructor}} -// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's -// default constructor is user-provided. -class Deleted3c { const DefaultedDefCtor2 a; }; // desired-note {{here}} -Deleted3c d3c; // desired-error {{deleted constructor}} +Deleted3a d3a; // expected-error {{implicitly-deleted default constructor}} +class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor1' would not be initialized}} +Deleted3b d3b; // expected-error {{implicitly-deleted default constructor}} +class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor2' would not be initialized}} +Deleted3c d3c; // expected-error {{implicitly-deleted default constructor}} class NotDeleted3a { const int a = 0; }; NotDeleted3a nd3a; class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; }; @@ -60,45 +65,51 @@ class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); }; NotDeleted3c nd3c; union NotDeleted3d { const int a; int b; }; NotDeleted3d nd3d; -// FIXME: this class should not have a deleted default constructor. -union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; // unexpected-note {{here}} -NotDeleted3e nd3e; // unexpected-error {{deleted constructor}} -// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2 is -// non-trivial. -union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; // unexpected-note {{here}} -NotDeleted3f nd3f; // unexpected-error {{deleted constructor}} +union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; +NotDeleted3e nd3e; +union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; +NotDeleted3f nd3f; +struct NotDeleted3g { union { const int a; int b; }; }; +NotDeleted3g nd3g; // - X is a union and all of its variant members are of const-qualified type (or // array thereof), -union Deleted4a { const int a; const int b; const UserProvidedDefCtor c; }; // expected-note {{here}} -Deleted4a d4a; // expected-error {{deleted constructor}} -union Deleted4b { const int a; int b; }; -Deleted4b d4b; +union Deleted4a { + const int a; + const int b; + const UserProvidedDefCtor c; // expected-note {{because field 'c' has a non-trivial default constructor}} +}; +Deleted4a d4a; // expected-error {{implicitly-deleted default constructor}} +union NotDeleted4a { const int a; int b; }; +NotDeleted4a nd4a; // - X is a non-union class and all members of any anonymous union member are of // const-qualified type (or array thereof), -struct Deleted5a { union { const int a; }; union { int b; }; }; // expected-note {{here}} -Deleted5a d5a; // expected-error {{deleted constructor}} -struct Deleted5b { union { const int a; int b; }; union { const int c; int d; }; }; -Deleted5b d5b; +struct Deleted5a { + union { const int a; }; // expected-note {{because all data members of an anonymous union member are const-qualified}} + union { int b; }; +}; +Deleted5a d5a; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted5a { union { const int a; int b; }; union { const int c; int d; }; }; +NotDeleted5a nd5a; // - any direct or virtual base class, or non-static data member with no // brace-or-equal-initializer, has class type M (or array thereof) and either // M has no default constructor or overload resolution as applied to M's default // constructor results in an ambiguity or in a function that is deleted or // inaccessible from the defaulted default constructor, or -struct Deleted6a : Deleted2a {}; // expected-note {{here}} -Deleted6a d6a; // expected-error {{deleted constructor}} -struct Deleted6b : virtual Deleted2a {}; // expected-note {{here}} -Deleted6b d6b; // expected-error {{deleted constructor}} -struct Deleted6c { Deleted2a a; }; // expected-note {{here}} -Deleted6c d6c; // expected-error {{deleted constructor}} -struct Deleted6d { DeletedDefCtor a; }; // expected-note {{here}} -Deleted6d d6d; // expected-error {{deleted constructor}} +struct Deleted6a : Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}} +Deleted6a d6a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6b : virtual Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}} +Deleted6b d6b; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6c { Deleted2a a; }; // expected-note {{because field 'a' has a deleted default constructor}} +Deleted6c d6c; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6d { DeletedDefCtor a; }; // expected-note {{because field 'a' has a deleted default constructor}} +Deleted6d d6d; // expected-error {{implicitly-deleted default constructor}} struct NotDeleted6a { DeletedDefCtor a = 0; }; NotDeleted6a nd6a; -struct Deleted6e { PrivateDefCtor a; }; // expected-note {{here}} -Deleted6e d6e; // expected-error {{deleted constructor}} +struct Deleted6e { PrivateDefCtor a; }; // expected-note {{because field 'a' has an inaccessible default constructor}} +Deleted6e d6e; // expected-error {{implicitly-deleted default constructor}} struct NotDeleted6b { PrivateDefCtor a = 0; }; NotDeleted6b nd6b; struct NotDeleted6c { Friend a; }; @@ -107,22 +118,22 @@ NotDeleted6c nd6c; // - any direct or virtual base class or non-static data member has a type with // a destructor that is deleted or inaccessible from the defaulted default // constructor. -struct Deleted7a : DeletedDtor {}; // expected-note {{here}} -Deleted7a d7a; // expected-error {{deleted constructor}} -struct Deleted7b : virtual DeletedDtor {}; // expected-note {{here}} -Deleted7b d7b; // expected-error {{deleted constructor}} -struct Deleted7c { DeletedDtor a; }; // expected-note {{here}} -Deleted7c d7c; // expected-error {{deleted constructor}} -struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{here}} -Deleted7d d7d; // expected-error {{deleted constructor}} -struct Deleted7e : PrivateDtor {}; // expected-note {{here}} -Deleted7e d7e; // expected-error {{deleted constructor}} -struct Deleted7f : virtual PrivateDtor {}; // expected-note {{here}} -Deleted7f d7f; // expected-error {{deleted constructor}} -struct Deleted7g { PrivateDtor a; }; // expected-note {{here}} -Deleted7g d7g; // expected-error {{deleted constructor}} -struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{here}} -Deleted7h d7h; // expected-error {{deleted constructor}} +struct Deleted7a : DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}} +Deleted7a d7a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7b : virtual DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}} +Deleted7b d7b; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7c { DeletedDtor a; }; // expected-note {{because field 'a' has a deleted destructor}} +Deleted7c d7c; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{because field 'a' has a deleted destructor}} +Deleted7d d7d; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7e : PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}} +Deleted7e d7e; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7f : virtual PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}} +Deleted7f d7f; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7g { PrivateDtor a; }; // expected-note {{field 'a' has an inaccessible destructor}} +Deleted7g d7g; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{field 'a' has an inaccessible destructor}} +Deleted7h d7h; // expected-error {{implicitly-deleted default constructor}} struct NotDeleted7i : Friend {}; NotDeleted7i d7i; struct NotDeleted7j : virtual Friend {}; @@ -159,11 +170,13 @@ static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor // Otherwise, the default constructor is non-trivial. class Trivial2 { Trivial2() = delete; }; -//static_assert(__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial"); -// FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial. -static_assert(!__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial"); +static_assert(__has_trivial_constructor(Trivial2), "Trivial2 is trivial"); class Trivial3 { Trivial3() = default; }; -//static_assert(__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial"); -// FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial. -static_assert(!__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial"); +static_assert(__has_trivial_constructor(Trivial3), "Trivial3 is trivial"); + +template<typename T> class Trivial4 { Trivial4() = default; }; +static_assert(__has_trivial_constructor(Trivial4<int>), "Trivial4 is trivial"); + +template<typename T> class Trivial5 { Trivial5() = delete; }; +static_assert(__has_trivial_constructor(Trivial5<int>), "Trivial5 is trivial"); diff --git a/test/CXX/special/class.ctor/p6-0x.cpp b/test/CXX/special/class.ctor/p6-0x.cpp new file mode 100644 index 0000000000000..8c8800f2de452 --- /dev/null +++ b/test/CXX/special/class.ctor/p6-0x.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +// Implicitly-defined default constructors are constexpr if the implicit +// definition would be. +struct NonConstexpr1 { // expected-note {{here}} + int a; +}; +struct NonConstexpr2 { // expected-note {{here}} + NonConstexpr1 nl; +}; +struct NonConstexpr2a : NonConstexpr1 { }; +constexpr NonConstexpr1 nc1 = NonConstexpr1(); // ok, does not call constructor +constexpr NonConstexpr2 nc2 = NonConstexpr2(); // ok, does not call constructor +constexpr NonConstexpr2a nc2a = NonConstexpr2a(); // ok, does not call constructor +constexpr int nc2_a = NonConstexpr2().nl.a; // ok +constexpr int nc2a_a = NonConstexpr2a().a; // ok +struct Helper { + friend constexpr NonConstexpr1::NonConstexpr1(); // expected-error {{follows non-constexpr declaration}} + friend constexpr NonConstexpr2::NonConstexpr2(); // expected-error {{follows non-constexpr declaration}} +}; + +struct Constexpr1 {}; +constexpr Constexpr1 c1 = Constexpr1(); // ok +struct NonConstexpr3 : virtual Constexpr1 {}; // expected-note {{struct with virtual base}} expected-note {{declared here}} +constexpr NonConstexpr3 nc3 = NonConstexpr3(); // expected-error {{non-literal type 'const NonConstexpr3'}} + +struct Constexpr2 { + int a = 0; +}; +constexpr Constexpr2 c2 = Constexpr2(); // ok + +int n; +struct Member { + Member() : a(n) {} + constexpr Member(int&a) : a(a) {} + int &a; +}; +struct NonConstexpr4 { // expected-note {{here}} + Member m; +}; +constexpr NonConstexpr4 nc4 = NonConstexpr4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4'}} +struct Constexpr3 { + constexpr Constexpr3() : m(n) {} + Member m; +}; +constexpr Constexpr3 c3 = Constexpr3(); // ok +struct Constexpr4 { + Constexpr3 m; +}; +constexpr Constexpr4 c4 = Constexpr4(); // ok + + +// This rule breaks some legal C++98 programs! +struct A {}; // expected-note {{here}} +struct B { + friend A::A(); // expected-error {{non-constexpr declaration of 'A' follows constexpr declaration}} +}; diff --git a/test/CXX/special/class.dtor/p10-0x.cpp b/test/CXX/special/class.dtor/p10-0x.cpp new file mode 100644 index 0000000000000..e10afb52e2b4b --- /dev/null +++ b/test/CXX/special/class.dtor/p10-0x.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// PR10127/N3031 +struct A { ~A(); }; +struct B {}; +template<typename T> +void b(const T *x, const A *y) { + x->~decltype(T())(); + x->~decltype(*x)(); // expected-error{{the type of object expression ('const int') does not match the type being destroyed ('decltype(*x)' (aka 'const int &')) in pseudo-destructor expression}} \ + expected-error{{no member named '~const struct A &' in 'A'}} + x->~decltype(int())(); // expected-error{{no member named '~int' in 'A'}} + + y->~decltype(*y)(); // expected-error{{destructor type 'decltype(*y)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}} + y->~decltype(T())(); // expected-error{{destructor type 'decltype(T())' in object destruction expression does not match the type 'const A' of the object being destroyed}} + y->~decltype(A())(); +} +template void b(const int*, const A*); // expected-note{{in instantiation of function template specialization 'b<int>' requested here}} +template void b(const A*,const A*); // expected-note{{in instantiation of function template specialization 'b<A>' requested here}} +void a(const A *x, int i, int *pi) { + x->~decltype(A())(); + x->~decltype(*x)(); // expected-error{{destructor type 'decltype(*x)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}} + x->~decltype()(); // expected-error{{expected expression}} + x->~decltype(B())(); // expected-error{{destructor type 'decltype(B())' (aka 'B') in object destruction expression does not match the type 'const A' of the object being destroyed}} + x->~decltype(x)(); // expected-error{{destructor type 'decltype(x)' (aka 'const A *') in object destruction expression does not match the type 'const A' of the object being destroyed}} + // this last one could be better, mentioning that the nested-name-specifier could be removed or a type name after the ~ + x->::A::~decltype(*x)(); // expected-error{{expected a class name after '~' to name a destructor}} + y->~decltype(A())(); // expected-error{{use of undeclared identifier 'y'}} + + typedef int *intp; + i->~decltype(int())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} + i.~decltype(int())(); + i->~decltype(intp())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} \ + expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} + i.~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} + pi->~decltype(int())(); + pi.~decltype(int())(); // expected-error{{the type of object expression ('int *') does not match the type being destroyed ('decltype(int())' (aka 'int')) in pseudo-destructor expression}} + pi.~decltype(intp())(); + pi->~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} +} diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp new file mode 100644 index 0000000000000..dbfa004440755 --- /dev/null +++ b/test/CXX/special/class.dtor/p5-0x.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +struct NonTrivDtor { + ~NonTrivDtor(); +}; +struct DeletedDtor { + ~DeletedDtor() = delete; // expected-note 5 {{deleted here}} +}; +class InaccessibleDtor { + ~InaccessibleDtor() = default; +}; + +// A defaulted destructor for a class X is defined as deleted if: + +// -- X is a union-like class that has a variant member with a non-trivial +// destructor. +union A1 { + A1(); + NonTrivDtor n; // expected-note {{destructor of union 'A1' is implicitly deleted because field 'n' has a non-trivial destructor}} +}; +A1 a1; // expected-error {{deleted function}} +struct A2 { + A2(); + union { + NonTrivDtor n; // expected-note {{because field 'n' has a non-trivial destructor}} + }; +}; +A2 a2; // expected-error {{deleted function}} +union A3 { + A3(); + NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} +}; +A3 a3; // expected-error {{deleted function}} +struct A4 { + A4(); + union { + NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} + }; +}; +A4 a4; // expected-error {{deleted function}} + +// -- any of the non-static data members has class type M (or array thereof) and +// M has a deleted or inaccessible destructor. +struct B1 { + B1(); + DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} +}; +B1 b1; // expected-error {{deleted function}} +struct B2 { + B2(); + InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} +}; +B2 b2; // expected-error {{deleted function}} +struct B3 { + B3(); + DeletedDtor a[4]; // expected-note {{because field 'a' has a deleted destructor}} +}; +B3 b3; // expected-error {{deleted function}} +struct B4 { + B4(); + InaccessibleDtor a[4]; // expected-note {{because field 'a' has an inaccessible destructor}} +}; +B4 b4; // expected-error {{deleted function}} +union B5 { + B5(); + // FIXME: Describe the anonymous union member better than ''. + union { // expected-note {{because field '' has a deleted destructor}} + DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} + }; +}; +B5 b5; // expected-error {{deleted function}} +union B6 { + B6(); + union { // expected-note {{because field '' has a deleted destructor}} + InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} + }; +}; +B6 b6; // expected-error {{deleted function}} + +// -- any direct or virtual base class has a deleted or inaccessible destructor. +struct C1 : DeletedDtor { C1(); } c1; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}} +struct C2 : InaccessibleDtor { C2(); } c2; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}} +struct C3 : virtual DeletedDtor { C3(); } c3; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}} +struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}} + +// -- for a virtual destructor, lookup of the non-array deallocation function +// results in an ambiguity or a function that is deleted or inaccessible. +class D1 { + void operator delete(void*); +public: + virtual ~D1() = default; +} d1; // ok +struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} + // implicitly-virtual destructor +} d2; // expected-error {{deleted function}} +struct D3 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} + virtual ~D3() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} + void operator delete(void*, double = 0.0); + void operator delete(void*, char = 0); +} d3; // expected-error {{deleted function}} +struct D4 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} + virtual ~D4() = default; // expected-note {{implicitly deleted here}} + void operator delete(void*) = delete; +} d4; // expected-error {{deleted function}} diff --git a/test/CXX/special/class.free/p1.cpp b/test/CXX/special/class.free/p1.cpp index e4fe127f9f578..5c0240b5dadc4 100644 --- a/test/CXX/special/class.free/p1.cpp +++ b/test/CXX/special/class.free/p1.cpp @@ -3,9 +3,9 @@ struct A { void *operator new(size_t) { - return this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} + return this; // expected-error {{invalid use of 'this' outside of a non-static member function}} } void *operator new[](size_t) { - return this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} + return this; // expected-error {{invalid use of 'this' outside of a non-static member function}} } }; diff --git a/test/CXX/special/class.free/p6.cpp b/test/CXX/special/class.free/p6.cpp index 555d4e9cfa944..fc4b2ae1acfdc 100644 --- a/test/CXX/special/class.free/p6.cpp +++ b/test/CXX/special/class.free/p6.cpp @@ -3,9 +3,9 @@ struct A { void operator delete(void*) { - (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} + (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}} } void operator delete[](void*) { - (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} + (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}} } }; diff --git a/test/CXX/special/class.inhctor/elsewhere.cpp b/test/CXX/special/class.inhctor/elsewhere.cpp index 60cfff80889ea..66afa17309faa 100644 --- a/test/CXX/special/class.inhctor/elsewhere.cpp +++ b/test/CXX/special/class.inhctor/elsewhere.cpp @@ -29,3 +29,29 @@ struct I1 : B1 { struct D1 : I1 { using B1::B1; // expected-error {{'B1' is not a direct base of 'D1', can not inherit constructors}} }; + +template<typename T> struct A {}; + +template<typename T> struct B : A<bool>, A<char> { + using A<T>::A; // expected-error {{'A<double>::', which is not a base class of 'B<double>'}} +}; +B<bool> bb; +B<char> bc; +B<double> bd; // expected-note {{here}} + +template<typename T> struct C : A<T> { + using A<bool>::A; // expected-error {{'A<bool>::', which is not a base class of 'C<char>'}} +}; +C<bool> cb; +C<char> cc; // expected-note {{here}} + +template<typename T> struct D : A<T> {}; +template<typename T> struct E : D<T> { + using A<bool>::A; // expected-error {{'A<bool>' is not a direct base of 'E<bool>', can not inherit}} +}; +E<bool> eb; // expected-note {{here}} + +template<typename T> struct F : D<bool> { + using A<T>::A; // expected-error {{'A<bool>' is not a direct base of 'F<bool>'}} +}; +F<bool> fb; // expected-note {{here}} diff --git a/test/CXX/special/class.inhctor/p3.cpp b/test/CXX/special/class.inhctor/p3.cpp index 989c17c8b462f..f71ab16c0f173 100644 --- a/test/CXX/special/class.inhctor/p3.cpp +++ b/test/CXX/special/class.inhctor/p3.cpp @@ -28,3 +28,21 @@ struct D3 : B3 { // expected-note 2 {{candidate constructor}} using B3::B3; // expected-note {{candidate constructor (inherited)}} }; D3 fd3() { return 1; } // expected-error {{no viable conversion}} + +template<typename T> struct T1 : B1 { + using B1::B1; +}; +template<typename T> struct T2 : T1<T> { + using T1<int>::T1; +}; +template<typename T> struct T3 : T1<int> { + using T1<T>::T1; +}; +struct U { + friend T1<int>::T1(int); + friend T1<int>::T1(int, int); + friend T2<int>::T2(int); + friend T2<int>::T2(int, int); + friend T3<int>::T3(int); + friend T3<int>::T3(int, int); +}; diff --git a/test/CXX/special/class.inhctor/p7.cpp b/test/CXX/special/class.inhctor/p7.cpp index 736754d8a3e30..9ae160f0547ab 100644 --- a/test/CXX/special/class.inhctor/p7.cpp +++ b/test/CXX/special/class.inhctor/p7.cpp @@ -2,7 +2,7 @@ // Straight from the standard struct B1 { - B1(int); // expected-note {{previous constructor}} + B1(int); // expected-note {{previous constructor}} expected-note {{conflicting constructor}} }; struct B2 { B2(int); // expected-note {{conflicting constructor}} @@ -16,3 +16,14 @@ struct D2 : B1, B2 { using B2::B2; D2(int); }; + +template<typename T> struct B3 { + B3(T); // expected-note {{previous constructor}} +}; +template<typename T> struct B4 : B3<T>, B1 { + B4(); + using B3<T>::B3; // expected-note {{inherited here}} + using B1::B1; // expected-error {{already inherited}} +}; +B4<char> b4c; +B4<int> b4i; // expected-note {{here}} diff --git a/test/CXX/special/class.init/class.base.init/p8-0x.cpp b/test/CXX/special/class.init/class.base.init/p8-0x.cpp index 3e26e4992d0d8..a108533beddb1 100644 --- a/test/CXX/special/class.init/class.base.init/p8-0x.cpp +++ b/test/CXX/special/class.init/class.base.init/p8-0x.cpp @@ -16,14 +16,17 @@ struct S { } s(0); union U { - int a = 0; + int a = 0; // desired-note 5 {{previous initialization is here}} char b = 'x'; // FIXME: these should all be rejected - U() {} // desired-error {{at most one member of a union may be initialized}} - U(int) : a(1) {} // desired-error {{at most one member of a union may be initialized}} - U(char) : b('y') {} // desired-error {{at most one member of a union may be initialized}} - U(double) : a(1), b('y') {} // desired-error {{at most one member of a union may be initialized}} + U() {} // desired-error {{initializing multiple members of union}} + U(int) : a(1) {} // desired-error {{initializing multiple members of union}} + U(char) : b('y') {} // desired-error {{initializing multiple members of union}} + // this expected note should be removed & the note should appear on the + // declaration of 'a' when this set of cases is handled correctly. + U(double) : a(1), // expected-note{{previous initialization is here}} desired-error {{initializing multiple members of union}} + b('y') {} // expected-error{{initializing multiple members of union}} }; // PR10954: variant members do not acquire an implicit initializer. diff --git a/test/CXX/special/class.temporary/p1.cpp b/test/CXX/special/class.temporary/p1.cpp index 384b1f89fda8d..4f6ac0a0029ed 100644 --- a/test/CXX/special/class.temporary/p1.cpp +++ b/test/CXX/special/class.temporary/p1.cpp @@ -31,8 +31,7 @@ namespace test1 { void test() { A a; - // FIXME: this error about variadics is bogus - foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} expected-error {{cannot pass object of non-trivial type 'test1::A' through variadic function}} + foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} } } diff --git a/test/CXX/stmt.stmt/stmt.ambig/p1-0x.cpp b/test/CXX/stmt.stmt/stmt.ambig/p1-0x.cpp new file mode 100644 index 0000000000000..81e8e25b4c4fa --- /dev/null +++ b/test/CXX/stmt.stmt/stmt.ambig/p1-0x.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct T { + struct x { + int m; + }; + x* operator->(); + void operator++(int); + void operator<<(int); + T(); + T(int); + T(int, int); +}; + +template<typename A, typename B, typename C, typename D, typename E> +void func(A, B, C, D, E); + +void func(int a, int c) { + T(a)->m = 7; + T(a)++; + T(a,5)<<c; + + T(*d)(int); + T(e)[5]; + T(f) = {1, 2}; + T(*g)(double(3)); // expected-error{{cannot initialize a variable of type 'T (*)' with an rvalue of type 'double'}} + func(a, d, e, f, g); +} + +void func2(int a, int c) { + decltype(T())(a)->m = 7; + decltype(T())(a)++; + decltype(T())(a,5)<<c; + + decltype(T())(*d)(int); + decltype(T())(e)[5]; + decltype(T())(f) = {1, 2}; + decltype(T())(*g)(double(3)); // expected-error{{cannot initialize a variable of type 'decltype(T()) (*)' (aka 'T *') with an rvalue of type 'double'}} + func(a, d, e, f, g); +} diff --git a/test/CXX/stmt.stmt/stmt.dcl/p3.cpp b/test/CXX/stmt.stmt/stmt.dcl/p3.cpp index 18fd34039ee58..f52e3b6d142db 100644 --- a/test/CXX/stmt.stmt/stmt.dcl/p3.cpp +++ b/test/CXX/stmt.stmt/stmt.dcl/p3.cpp @@ -30,7 +30,7 @@ struct Y { void test_Y() { goto end; // expected-error{{goto into protected scope}} - Y y; // expected-note{{jump bypasses variable initialization}} + Y y; // expected-note{{jump bypasses variable with a non-trivial destructor}} end: return; } @@ -41,7 +41,7 @@ struct Z { void test_Z() { goto end; // expected-error{{goto into protected scope}} - Z z; // expected-note{{jump bypasses variable initialization}} + Z z; // expected-note{{jump bypasses initialization of non-POD variable}} end: return; } diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp index b157fd4b0f922..a45b35f715928 100644 --- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp +++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp @@ -128,7 +128,7 @@ void g() { void *begin(); // expected-note {{selected 'begin' function with iterator type 'void *'}} void *end(); }; - for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void type}} + for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}} } struct NoNotEq { diff --git a/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp b/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp new file mode 100644 index 0000000000000..000c870d59018 --- /dev/null +++ b/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +struct Value { + constexpr Value(int n) : n(n) {} + constexpr operator short() { return n; } + int n; +}; +enum E { E0, E1 }; +struct Alt { + constexpr operator E() { return E0; } +}; + +constexpr short s = Alt(); + +void test(Value v) { + switch (v) { + case Alt(): + case E1: + case Value(2): + case 3: + break; + } + switch (Alt a = Alt()) { + case Alt(): + case E1: + case Value(2): + case 3: + break; + } + switch (E0) { + case Alt(): + case E1: + // FIXME: These should produce a warning that 2 and 3 are not values of the + // enumeration. + case Value(2): + case 3: + break; + } +} diff --git a/test/CXX/temp/p3.cpp b/test/CXX/temp/p3.cpp index 16ebb381fd120..c146bc4faadec 100644 --- a/test/CXX/temp/p3.cpp +++ b/test/CXX/temp/p3.cpp @@ -6,11 +6,9 @@ template<typename T> struct S { template<typename T> int S<T>::a, S<T>::b; // expected-error {{can only declare a single entity}} -// FIXME: the last two diagnostics here are terrible. template<typename T> struct A { static A a; } A<T>::a; // expected-error {{expected ';' after struct}} \ expected-error {{use of undeclared identifier 'T'}} \ - expected-error {{cannot name the global scope}} \ - expected-error {{no member named 'a' in the global namespace}} + expected-warning{{extra qualification}} template<typename T> struct B { } f(); // expected-error {{expected ';' after struct}} \ expected-error {{requires a type specifier}} diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp new file mode 100644 index 0000000000000..59ce8b68b7c8a --- /dev/null +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +namespace std { + typedef decltype(nullptr) nullptr_t; +} + +template<int *ip> struct IP { // expected-note 4 {{template parameter is declared here}} + IP<ip> *ip2; +}; + +constexpr std::nullptr_t get_nullptr() { return nullptr; } + +constexpr std::nullptr_t np = nullptr; + +std::nullptr_t nonconst_np; // expected-note{{declared here}} + +IP<0> ip0; // expected-error{{null non-type template argument must be cast to template parameter type 'int *'}} +IP<(0)> ip1; // expected-error{{null non-type template argument must be cast to template parameter type 'int *'}} +IP<nullptr> ip2; +IP<get_nullptr()> ip3; +IP<(int*)0> ip4; +IP<np> ip5; +IP<nonconst_np> ip5; // expected-error{{non-type template argument of type 'std::nullptr_t' (aka 'nullptr_t') is not a constant expression}} \ +// expected-note{{read of non-constexpr variable 'nonconst_np' is not allowed in a constant expression}} +IP<(float*)0> ip6; // expected-error{{null non-type template argument of type 'float *' does not match template parameter of type 'int *'}} + +struct X { }; +template<int X::*pm> struct PM { // expected-note 2 {{template parameter is declared here}} + PM<pm> *pm2; +}; + +PM<0> pm0; // expected-error{{null non-type template argument must be cast to template parameter type 'int X::*'}} +PM<(0)> pm1; // expected-error{{null non-type template argument must be cast to template parameter type 'int X::*'}} +PM<nullptr> pm2; +PM<get_nullptr()> pm3; +PM<(int X::*)0> pm4; +PM<np> pm5; + +template<int (X::*pmf)(int)> struct PMF { // expected-note 2 {{template parameter is declared here}} + PMF<pmf> *pmf2; +}; + +PMF<0> pmf0; // expected-error{{null non-type template argument must be cast to template parameter type 'int (X::*)(int)'}} +PMF<(0)> pmf1; // expected-error{{null non-type template argument must be cast to template parameter type 'int (X::*)(int)'}} +PMF<nullptr> pmf2; +PMF<get_nullptr()> pmf3; +PMF<(int (X::*)(int))0> pmf4; +PMF<np> pmf5; + + +template<std::nullptr_t np> struct NP { // expected-note 2{{template parameter is declared here}} + NP<np> *np2; +}; + +NP<nullptr> np1; +NP<np> np2; +NP<get_nullptr()> np3; +NP<0> np4; // expected-error{{null non-type template argument must be cast to template parameter type 'std::nullptr_t' (aka 'nullptr_t')}} +constexpr int i = 7; +NP<i> np5; // expected-error{{non-type template argument of type 'const int' cannot be converted to a value of type 'std::nullptr_t'}} diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp index 14dace89a156b..c4db0027052ce 100644 --- a/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple=x86_64-linux-gnu %s -// C++0x [temp.arg.nontype]p1: +// C++11 [temp.arg.nontype]p1: // // A template-argument for a non-type, non-template template-parameter shall // be one of: @@ -19,27 +19,65 @@ namespace non_type_tmpl_param { 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 +// -- a constant expression that designates the address of an object with +// static storage duration and external or internal linkage or a function +// with external or internal linkage, including function templates and +// function template-ids, but excluting non-static class members, expressed +// (ignoring parentheses) as & id-expression, except that the & may be +// omitted if the name refers to a function or array and shall be omitted +// if the corresopnding template-parameter is a reference; or namespace addr_of_obj_or_func { - template <int* p> struct X0 { }; + template <int* p> struct X0 { }; // expected-note 4{{here}} template <int (*fp)(int)> struct X1 { }; - // FIXME: Add reference template parameter tests. + template <int &p> struct X2 { }; // expected-note 4{{here}} + template <const int &p> struct X2k { }; // expected-note {{here}} + template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}} int i = 42; int iarr[10]; int f(int i); + const int ki = 9; // expected-note 5{{here}} + __thread int ti = 100; // expected-note 2{{here}} + static int f_internal(int); // expected-note 4{{here}} template <typename T> T f_tmpl(T t); + void test() { - X0<&i> x0a; + X0<i> x0a; // expected-error {{must have its address taken}} + X0<&i> x0a_addr; X0<iarr> x0b; - X1<&f> x1a; - X1<f> x1b; - X1<f_tmpl> x1c; - X1<f_tmpl<int> > x1d; + X0<&iarr> x0b_addr; // expected-error {{cannot be converted to a value of type 'int *'}} + X0<ki> x0c; // expected-error {{must have its address taken}} expected-warning {{internal linkage is a C++11 extension}} + X0<&ki> x0c_addr; // expected-error {{cannot be converted to a value of type 'int *'}} expected-warning {{internal linkage is a C++11 extension}} + X0<&ti> x0d_addr; // expected-error {{refers to thread-local object}} + X1<f> x1a; + X1<&f> x1a_addr; + X1<f_tmpl> x1b; + X1<&f_tmpl> x1b_addr; + X1<f_tmpl<int> > x1c; + X1<&f_tmpl<int> > x1c_addr; + X1<f_internal> x1d; // expected-warning {{internal linkage is a C++11 extension}} + X1<&f_internal> x1d_addr; // expected-warning {{internal linkage is a C++11 extension}} + X2<i> x2a; + X2<&i> x2a_addr; // expected-error {{address taken}} + X2<iarr> x2b; // expected-error {{cannot bind to template argument of type 'int [10]'}} + X2<&iarr> x2b_addr; // expected-error {{address taken}} + X2<ki> x2c; // expected-error {{ignores qualifiers}} expected-warning {{internal linkage is a C++11 extension}} + X2k<ki> x2kc; // expected-warning {{internal linkage is a C++11 extension}} + X2k<&ki> x2kc_addr; // expected-error {{address taken}} expected-warning {{internal linkage is a C++11 extension}} + X2<ti> x2d_addr; // expected-error {{refers to thread-local object}} + X3<f> x3a; + X3<&f> x3a_addr; // expected-error {{address taken}} + X3<f_tmpl> x3b; + X3<&f_tmpl> x3b_addr; // expected-error {{address taken}} + X3<f_tmpl<int> > x3c; + X3<&f_tmpl<int> > x3c_addr; // expected-error {{address taken}} + X3<f_internal> x3d; // expected-warning {{internal linkage is a C++11 extension}} + X3<&f_internal> x3d_addr; // expected-error {{address taken}} expected-warning {{internal linkage is a C++11 extension}} + + int n; // expected-note {{here}} + X0<&n> x0_no_linkage; // expected-error {{non-type template argument refers to object 'n' that does not have linkage}} + struct Local { static int f() {} }; // expected-note {{here}} + X1<&Local::f> x1_no_linkage; // expected-error {{non-type template argument refers to function 'f' that does not have linkage}} } } diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp new file mode 100644 index 0000000000000..f8cc00947480b --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<typename T> struct A { + enum E : T; // expected-note {{here}} + E v; + E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}} + E g() { return E::e1; } + E h(); +}; + +A<int> a; +A<int>::E a0 = A<int>().v; +int n = A<int>::E::e1; // expected-error {{implicit instantiation of undefined member}} + +template<typename T> enum A<T>::E : T { e1, e2 }; + +// FIXME: Now that A<T>::E is defined, we are supposed to inject its enumerators +// into the already-instantiated class A<T>. This seems like a really bad idea, +// though, so we don't implement that, but what we do implement is inconsistent. +// +// Either do as the standard says, or only include enumerators lexically defined +// within the class in its scope. +A<int>::E a1 = A<int>::e1; // expected-error {{no member named 'e1' in 'A<int>'}} + +A<char>::E a2 = A<char>::e2; + +template<typename T> typename A<T>::E A<T>::h() { return e2; } +A<short>::E a3 = A<short>().h(); + + +template<typename T> struct B { + enum class E; + E v; + E f() { return E::e1; } + E g(); +}; + +B<int> b; +B<int>::E b0 = B<int>().v; + +template<typename T> enum class B<T>::E { e1, e2 }; +B<int>::E b1 = B<int>::E::e1; + +B<char>::E b2 = B<char>::E::e2; + +template<typename T> typename B<T>::E B<T>::g() { return e2; } +B<short>::E b3 = B<short>().g(); + + +// Enumeration members of class templates can be explicitly specialized. For +// unscoped enumerations, specializations must be defined before the primary +// template is, since otherwise the primary template will be implicitly +// instantiated when we parse the nested name specifier. +template<> enum A<long long>::E : long long { e3, e4 }; // expected-error {{explicit specialization of 'E' after instantiation}} expected-note {{first required here}} + +template<> enum class B<long long>::E { e3, e4 }; +B<long long>::E b4 = B<long long>::E::e4; + +B<long>::E b5; +template<> enum class B<long>::E { e5 }; +void fb5() { b5 = decltype(b5)::e5; } +B<long>::E b6 = B<long>::E::e5; + + +template<typename T> struct C { + enum class E : T; +}; + +template<> enum class C<long long>::E : long long { e3, e4 }; +C<long long>::E c0 = C<long long>::E::e3; + +C<long>::E c1; +template<> enum class C<long>::E : long { e5 }; +void fc1() { c1 = decltype(c1)::e5; } +C<long>::E c2 = C<long>::E::e5; + +template<> enum class C<int>::E : int { e6 }; +template<typename T> enum class C<T>::E : T { e0 }; +C<int>::E c3 = C<int>::E::e6; +C<int>::E c4 = C<int>::E::e0; // expected-error {{no member named 'e0' in 'C<int>::E'}} + + +// Enumeration members can't be partially-specialized. +template<typename T> enum class B<T*>::E { e5, e6 }; // expected-error {{nested name specifier for a declaration cannot depend on a template parameter}} + + +// Explicit specializations can be forward-declared. +template<typename T> +struct D { + enum class E { e1 }; +}; +template<> enum class D<int>::E; +D<int>::E d1 = D<int>::E::e1; // expected-error {{incomplete type 'D<int>::E'}} +template<> enum class D<int>::E { e2 }; +D<int>::E d2 = D<int>::E::e2; +D<char>::E d3 = D<char>::E::e1; // expected-note {{first required here}} +D<char>::E d4 = D<char>::E::e2; // expected-error {{no member named 'e2'}} +template<> enum class D<char>::E { e3 }; // expected-error {{explicit specialization of 'E' after instantiation}} + +template<> enum class D<short>::E; +struct F { + // Per C++11 [class.friend]p3, these friend declarations have no effect. + // Only classes and functions can be friends. + template<typename T> friend enum D<T>::E; + template<> friend enum D<short>::E; + + template<> friend enum D<double>::E { e3 }; // expected-error {{cannot define a type in a friend declaration}} + +private: + static const int n = 1; // expected-note {{private here}} +}; +template<> enum class D<short>::E { + e = F::n // expected-error {{private member}} +}; + +class Access { + friend class X; + + template<typename T> + class Priv { + friend class X; + + enum class E : T; + }; + + class S { + typedef int N; // expected-note {{here}} + static const int k = 3; // expected-note {{here}} + + friend class Priv<char>; + }; + + static const int k = 5; +}; + +template<> enum class Access::Priv<Access::S::N>::E + : Access::S::N { // expected-error {{private member}} + a = Access::k, // ok + b = Access::S::k // expected-error {{private member}} +}; + +template<typename T> enum class Access::Priv<T>::E : T { + c = Access::k, + d = Access::S::k +}; + +class X { + Access::Priv<int>::E a = Access::Priv<int>::E::a; + Access::Priv<char>::E c = Access::Priv<char>::E::d; + // FIXME: We should see an access error for this enumerator. + Access::Priv<short>::E b = Access::Priv<short>::E::d; +}; diff --git a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp new file mode 100644 index 0000000000000..fb727543efa5b --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T, typename U> struct pair { }; +template<typename ...Types> struct tuple { }; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +namespace ExpandIntoFixed { + template<typename T, + typename U, + typename V = pair<T, U>, + typename W = V*> + class X0 { }; + + template<typename ...Ts> + class X1 { + public: + typedef X0<Ts...> type; + }; + + static_assert(is_same<X1<int, int>::type, + X0<int, int, pair<int, int>, pair<int, int>*>>::value, + "fails with two default arguments"); + + static_assert(is_same<X1<int, int, float>::type, + X0<int, int, float, float*>>::value, + "fails with one default argument"); + + static_assert(is_same<X1<int, int, float, double>::type, + X0<int, int, float, double>>::value, + "fails with no default arguments"); +} + +namespace ExpandIntoFixedShifted { + template<typename T, + typename U, + typename V = pair<T, U>, + typename W = V*> + class X0 { }; + + template<typename ...Ts> + class X1 { + public: + typedef X0<char, Ts...> type; + }; + + static_assert(is_same<X1<int>::type, + X0<char, int, pair<char, int>, pair<char, int>*>>::value, + "fails with two default arguments"); + + static_assert(is_same<X1<int, float>::type, + X0<char, int, float, float*>>::value, + "fails with one default argument"); + + static_assert(is_same<X1<int, float, double>::type, + X0<char, int, float, double>>::value, + "fails with no default arguments"); +} + +namespace Deduction { + template <typename X, typename Y = double> struct Foo {}; + template <typename ...Args> tuple<Args...> &foo(Foo<Args...>); + + void call_foo(Foo<int, float> foo_if, Foo<int> foo_i) { + tuple<int, float> &t1 = foo(foo_if); + tuple<int, double> &t2 = foo(foo_i); + } +} + +namespace PR9021a { + template<typename, typename> + struct A { }; + + template<typename ...T> + struct B { + A<T...> a1; + }; + + void test() { + B<int, int> c; + } +} + +namespace PR9021b { + template<class, class> + struct t2 + { + + }; + + template<template<class...> class M> + struct m + { + template<class... B> + using inner = M<B...>; + }; + + m<t2> sta2; +} + +namespace PartialSpecialization { + template<typename T, typename U, typename V = U> + struct X0; // expected-note{{template is declared here}} + + template<typename ...Ts> + struct X0<Ts...> { + }; + + X0<int> x0i; // expected-error{{too few template arguments for class template 'X0'}} + X0<int, float> x0if; + X0<int, float, double> x0ifd; +} + +namespace FixedAliasTemplate { + template<typename,typename,typename> struct S {}; + template<typename T, typename U> using U = S<T, int, U>; + template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); + S<int, int, double> &s1 = f({}, 0, 0.0); +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 05e492167cbee..d8294a1f154a0 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -20,6 +20,52 @@ struct is_same<T, T> { // FIXME: Several more bullets to go +// In a function parameter pack, the pattern is the parameter-declaration +// without the ellipsis. +namespace PR11850 { + template<typename ...T> struct S { + int f(T...a, int b) { return b; } + }; + S<> s; + S<int*, char, const double&> t; + int k = s.f(0); + int l = t.f(&k, 'x', 5.9, 4); + + template<typename ...As> struct A { + template<typename ...Bs> struct B { + template<typename ...Cs> struct C { + C(As..., Bs..., int &k, Cs...); + }; + }; + }; + A<>::B<>::C<> c000(k); + A<int>::B<>::C<int> c101(1, k, 3); + A<>::B<int>::C<int> c011(1, k, 3); + A<int>::B<int>::C<> c110(1, 2, k); + A<int, int>::B<int, int>::C<int, int> c222(1, 2, 3, 4, k, 5, 6); + A<int, int, int>::B<>::C<> c300(1, 2, 3, k); + + int &f(); + char &f(void*); + template<typename ...A> struct U { + template<typename ...B> struct V { + auto g(A...a, B...b) -> decltype(f(a...)); + }; + }; + U<>::V<int*> v0; + U<int*>::V<> v1; + int &v0f = v0.g(0); + char &v1f = v1.g(0); +} +namespace PR12096 { + void Foo(int) {} + void Foo(int, int) = delete; + template<typename ...Args> struct Var { + Var(const Args &...args, int *) { Foo(args...); } + }; + Var<int> var(1, 0); +} + // In an initializer-list (8.5); the pattern is an initializer-clause. // Note: this also covers expression-lists, since expression-list is // just defined as initializer-list. @@ -37,7 +83,8 @@ template void initializer_list_expansion<1, 2, 3, 4, 5, 6>(); // expected-note{{ namespace PR8977 { struct A { }; template<typename T, typename... Args> void f(Args... args) { - T t(args...); + // An empty expression-list performs value initialization. + constexpr T t(args...); }; template void f<A>(); @@ -90,6 +137,16 @@ struct X { X() : member()... { } // expected-error{{pack expansion for initialization of member 'member'}} }; +// There was a bug in the delayed parsing code for the +// following case. +template<typename ...T> +struct DelayedParseTest : T... +{ + int a; + DelayedParseTest(T... i) : T{i}..., a{10} {} +}; + + // In a template-argument-list (14.3); the pattern is a template-argument. template<typename ...Types> struct tuple_of_refs { diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp index 0f409e709e980..6955219e7ae34 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -160,9 +160,9 @@ struct TestUnexpandedTTP { }; // Test for unexpanded parameter packs in declarations. -// FIXME: Attributes? template<typename T, typename... Types> -struct TestUnexpandedDecls : T{ +// FIXME: this should test that the diagnostic reads "type contains..." +struct alignas(Types) TestUnexpandedDecls : T{ // expected-error{{expression contains unexpanded parameter pack 'Types'}} void member_function(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} void member_function () throw(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} operator Types() const; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} @@ -185,10 +185,16 @@ struct TestUnexpandedDecls : T{ void test_initializers() { T copy_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} - T direct_init(0, static_cast<Types>(0)); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + T direct_init(0, static_cast<Types>(0)); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} T list_init = { static_cast<Types>(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}} } + T in_class_member_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + TestUnexpandedDecls() : + Types(static_cast<Types>(0)), // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + Types(static_cast<Types>(0))..., + in_class_member_init(static_cast<Types>(0)) {} // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + void default_function_args(T = static_cast<Types>(0)); // expected-error{{default argument contains unexpanded parameter pack 'Types'}} template<typename = Types*> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp index 9236efce2b83d..83b5f23140113 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp @@ -10,3 +10,11 @@ namespace PR8598 { void g() { (f)(&X::f, 0); } } + +namespace PR12132 { + template<typename S> void fun(const int* const S::* member) {} + struct A { int* x; }; + void foo() { + fun(&A::x); + } +} 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 index 16b5cd297d8bb..8b18189bb3da6 100644 --- 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 @@ -50,7 +50,7 @@ namespace test0 { 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}} + // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} template<class T> void temp(T); void test0() { @@ -111,3 +111,18 @@ namespace rdar8360106 { f2(&g, 1); } } + +namespace PR11713 { + template<typename T> + int f(int, int, int); + + template<typename T> + float f(float, float); + + template<typename R, typename B1, typename B2, typename A1, typename A2> + R& g(R (*)(B1, B2), A1, A2); + + void h() { + float &fr = g(f<int>, 1, 2); + } +} diff --git a/test/CXX/temp/temp.param/p11-0x.cpp b/test/CXX/temp/temp.param/p11-0x.cpp index 1971aa10c2c73..d2276a3bced3b 100644 --- a/test/CXX/temp/temp.param/p11-0x.cpp +++ b/test/CXX/temp/temp.param/p11-0x.cpp @@ -24,8 +24,9 @@ template<template<class> class M = vector, template<class> class... Metas> // If a template-parameter of a primary class template or alias template is a // template parameter pack, it shall be the last template-parameter. template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} - int After> + int After, int After2> struct X0t; +X0t<int> pr9789(); template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} int After> using A0t = int; diff --git a/test/CXX/temp/temp.param/p5.cpp b/test/CXX/temp/temp.param/p5.cpp new file mode 100644 index 0000000000000..3cbb3b7c0103f --- /dev/null +++ b/test/CXX/temp/temp.param/p5.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify %s -std=c++11 + +template<const int I> struct S { + decltype(I) n; + int &&r = I; +}; +S<5> s; + +template<typename T, T v> struct U { + decltype(v) n; + int &&r = v; +}; +U<const int, 6> u; diff --git a/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp b/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp new file mode 100644 index 0000000000000..0aba4028b7699 --- /dev/null +++ b/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<int n> struct S; + +template<int n> struct T { + T() { + // An identifier is value-dependent if it is: + // - a name declared with a dependent type + S<n> s; + S<s> check1; // ok, s is value-dependent + // - the name of a non-type template parameter + typename S<n>::T check2; // ok, n is value-dependent + // - a constant with literal type and is initialized with an expression + // that is value-dependent. + const int k = n; + typename S<k>::T check3a; // ok, u is value-dependent + + constexpr const int *p = &k; + typename S<*p>::T check3b; // ok, p is value-dependent + + // (missing from the standard) + // - a reference and is initialized with an expression that is + // value-dependent. + const int &i = k; + typename S<i>::T check4; // ok, i is value-dependent + } +}; diff --git a/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp b/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp new file mode 100644 index 0000000000000..68a41c7184c02 --- /dev/null +++ b/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++98 -verify %s + +template<int n> struct S; + +template<int n> struct T { + T() { + // An identifier is value-dependent if it is: + // - a name declared with a dependent type + S<n> s; + S<s> check1; // ok, s is value-dependent + // - the name of a non-type template parameter + typename S<n>::T check2; // ok, n is value-dependent + // - a constant with literal type and is initialized with an expression + // that is value-dependent. + const int k = n; + typename S<k>::T check3; // ok, u is value-dependent + + const int &i = k; + typename S<i>::T check4; // expected-error {{not an integral constant expression}} expected-error {{qualified name}} + } +}; diff --git a/test/CXX/temp/temp.spec/p5.cpp b/test/CXX/temp/temp.spec/p5.cpp index ba99dd7093a20..0e69a26b04e26 100644 --- a/test/CXX/temp/temp.spec/p5.cpp +++ b/test/CXX/temp/temp.spec/p5.cpp @@ -14,9 +14,10 @@ struct X0 { }; template<typename T> -T X0<T>::value = 3.14; +T X0<T>::value = 3.14; // expected-warning{{implicit conversion turns literal floating-point number into integer}} -template struct X0<int>; // expected-note{{previous explicit instantiation}} +template struct X0<int>; // expected-note{{previous explicit instantiation}} \ + expected-note{{requested here}} template struct X0<int>; // expected-error{{duplicate explicit instantiation}} template void X0<float>::f(float); // expected-note{{previous explicit instantiation}} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp index f04c544aa4481..aecbfb5649f3c 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp @@ -207,3 +207,128 @@ namespace template_class_spec_perClassDecl_nested static void foo(); }; } + + +namespace spec_vs_expl_inst { + + // Test all permutations of Specialization, + // explicit instantiation Declaration, and explicit instantiation defInition. + + namespace SDI { // PR11558 + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + } + + namespace SID { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::ISD::BasicStringPiece<int>'}} + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + } + + namespace IDS { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::IDS::BasicStringPiece<int>'}} // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece<int> { }; + } + + namespace DIS { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DIS::BasicStringPiece<int>'}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; + } + + namespace DSI { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DSI::BasicStringPiece<int>'}} + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; + } + + // The same again, with a defined template class. + + namespace SDI_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + } + + namespace SID_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::ISD_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + extern template class BasicStringPiece<int>; + } + + namespace IDS_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece<int>'}} + } + + namespace DIS_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + extern template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DIS_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + } + + namespace DSI_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + extern template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DSI_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + template class BasicStringPiece<int>; + } + + // And some more random tests. + + namespace SII_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{previous explicit instantiation is here}} + template class BasicStringPiece<int>; // expected-error {{duplicate explicit instantiation of 'BasicStringPiece<int>'}} + } + + namespace SIS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece<int>'}} + } + + namespace SDS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece<int>'}} + } + + namespace SDIS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece<int>'}} + } + +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp index acfbb46447de4..b0a19fb93a6c4 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp @@ -33,7 +33,7 @@ namespace N0 { template<> void N0::f0(int) { } // okay namespace N1 { - template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}} + template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} } template<> void N0::f0(double) { } @@ -129,7 +129,7 @@ template<> int N0::X0<int>::member; template<> float N0::X0<float>::member = 3.14f; namespace N1 { - template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}} + template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}} } // -- member class of a class template @@ -227,7 +227,7 @@ void N0::X0<void*>::ft1(void *, float) { } namespace N1 { template<> template<> - void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}} + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp index 229523557008e..c972bf7c7d0aa 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -33,10 +33,11 @@ namespace N0 { template<> void N0::f0(int) { } // okay namespace N1 { - template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}} + template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} } -template<> void N0::f0(double) { } // expected-warning{{originally be declared}} +template<> void N0::f0(double); // expected-warning{{C++11 extension}} +template<> void N0::f0(double) { } struct X1 { template<typename T> void f(T); @@ -75,7 +76,7 @@ void N0::X0<T>::ft1(T t, U u) { template<typename T> T N0::X0<T>::member; -template<> struct N0::X0<void> { }; // expected-warning{{originally}} +template<> struct N0::X0<void> { }; // expected-warning{{C++11 extension}} N0::X0<void> test_X0; namespace N1 { @@ -124,12 +125,12 @@ NonDefaultConstructible &get_static_member() { return N0::X0<NonDefaultConstructible>::member; } -template<> int N0::X0<int>::member; // expected-warning{{originally}} +template<> int N0::X0<int>::member; // expected-warning{{C++11 extension}} template<> float N0::X0<float>::member = 3.14f; namespace N1 { - template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}} + template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}} } // -- member class of a class template @@ -152,7 +153,7 @@ namespace N0 { } template<> -struct N0::X0<long>::Inner { }; // expected-warning{{originally}} +struct N0::X0<long>::Inner { }; // expected-warning{{C++11 extension}} template<> struct N0::X0<float>::Inner { }; @@ -227,7 +228,7 @@ void N0::X0<void*>::ft1(void *, float) { } // expected-warning{{function templat namespace N1 { template<> template<> - void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}} + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} } diff --git a/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp index 97e78fd791fac..80f0598cb1d19 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp @@ -13,3 +13,12 @@ struct Y { }; template constexpr int Y<int>::f(); // expected-error{{explicit instantiation cannot be 'constexpr'}} + +template<typename T> +struct Z { + enum E : T { e1, e2 }; + T t; // expected-note {{refers here}} +}; + +template enum Z<int>::E; // expected-error {{enumerations cannot be explicitly instantiated}} +template int Z<int>::t; // expected-error {{explicit instantiation of 't' does not refer to}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p2.cpp b/test/CXX/temp/temp.spec/temp.explicit/p2.cpp index 822f881712120..1dfcf0ce2d2f5 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p2.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s // Example from the standard template<class T> class Array { void mf() { } }; diff --git a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp index 48c42c399a468..38ae7688a0b5a 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s // A declaration of a function template shall be in scope at the point of the // explicit instantiation of the function template. @@ -72,3 +72,10 @@ namespace PR7979 { template <typename T> int S<T>::i; template <typename T> void S<T>::S2::h() {} } + +namespace PR11599 { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + + extern template class BasicStringPiece<int>; // expected-error{{explicit instantiation of undefined template 'PR11599::BasicStringPiece<int>}} + template class BasicStringPiece<int>; +} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp index d304374115138..09c428e01df3b 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -43,6 +43,6 @@ namespace test0 { // inappropriately instantiating this template. void *ptr = x; } - extern template class foo<char>; + extern template class foo<char>; // expected-warning {{extern templates are a C++11 extension}} template class foo<char>; } diff --git a/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/test/CXX/temp/temp.spec/temp.explicit/p5.cpp index 7522d02ffa19b..8422c519a760c 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p5.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p5.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s namespace N { template<class T> class Y { // expected-note{{explicit instantiation refers here}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p8.cpp b/test/CXX/temp/temp.spec/temp.explicit/p8.cpp index 0c5aec3b0bc8a..550078ab147c9 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p8.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p8.cpp @@ -1,16 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template<typename T> struct X0 { struct MemberClass; - + T* f0(T* ptr); - + static T* static_member; }; -template class X0<int>; // okay -template class X0<int(int)>; // okay; nothing gets instantiated. +template class X0<int(int)>; // ok; nothing gets instantiated. template<typename T> struct X0<T>::MemberClass { @@ -25,3 +24,17 @@ T* X0<T>::f0(T* ptr) { template<typename T> T* X0<T>::static_member = 0; +template class X0<int>; // ok + + +template<typename T> +struct X1 { + enum class E { + e = T::error // expected-error 2{{no members}} + }; +}; +template struct X1<int>; // expected-note {{here}} + +extern template struct X1<char>; // ok + +template struct X1<char>; // expected-note {{here}} diff --git a/test/CXX/temp/temp.spec/temp.inst/p1.cpp b/test/CXX/temp/temp.spec/temp.inst/p1.cpp new file mode 100644 index 0000000000000..8684fc4dabd9c --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.inst/p1.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// The implicit specialization of a class template specialuzation causes the +// implicit instantiation of the declarations, but not the definitions or +// default arguments, of: + +// FIXME: Many omitted cases + +// - scoped member enumerations +namespace ScopedEnum { + template<typename T> struct ScopedEnum1 { + enum class E { + e = T::error // expected-error {{'double' cannot be used prior to '::'}} + }; + }; + ScopedEnum1<int> se1; // ok + + template<typename T> struct ScopedEnum2 { + enum class E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + ScopedEnum2<void*> se2; // expected-note {{here}} + + template<typename T> struct UnscopedEnum3 { + enum class E : T { + e = 4 + }; + int arr[(int)E::e]; + }; + UnscopedEnum3<int> ue3; // ok + + ScopedEnum1<double>::E e1; // ok + ScopedEnum1<double>::E e2 = decltype(e2)::e; // expected-note {{in instantiation of enumeration 'ScopedEnum::ScopedEnum1<double>::E' requested here}} + + // The behavior for enums defined within function templates is not clearly + // specified by the standard. We follow the rules for enums defined within + // class templates. + template<typename T> + int f() { + enum class E { + e = T::error + }; + return (int)E(); + } + int test1 = f<int>(); + + template<typename T> + int g() { + enum class E { + e = T::error // expected-error {{has no members}} + }; + return E::e; // expected-note {{here}} + } + int test2 = g<int>(); // expected-note {{here}} +} + +// And it cases the implicit instantiations of the definitions of: + +// - unscoped member enumerations +namespace UnscopedEnum { + template<typename T> struct UnscopedEnum1 { + enum E { + e = T::error // expected-error {{'int' cannot be used prior to '::'}} + }; + }; + UnscopedEnum1<int> ue1; // expected-note {{here}} + + template<typename T> struct UnscopedEnum2 { + enum E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + UnscopedEnum2<void*> ue2; // expected-note {{here}} + + template<typename T> struct UnscopedEnum3 { + enum E : T { + e = 4 + }; + int arr[E::e]; + }; + UnscopedEnum3<int> ue3; // ok + + template<typename T> + int f() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return (int)E(); + } + int test1 = f<int>(); // expected-note {{here}} + + template<typename T> + int g() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return E::e; + } + int test2 = g<int>(); // expected-note {{here}} +} + +// FIXME: +//- - member anonymous unions |