diff options
Diffstat (limited to 'test/CXX')
82 files changed, 1945 insertions, 187 deletions
diff --git a/test/CXX/basic/basic.link/p6.cpp b/test/CXX/basic/basic.link/p6.cpp new file mode 100644 index 0000000..8faec76 --- /dev/null +++ b/test/CXX/basic/basic.link/p6.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++11 [basic.link]p6: +// The name of a function declared in block scope and the name +// of a variable declared by a block scope extern declaration +// have linkage. If there is a visible declaration of an entity +// with linkage having the same name and type, ignoring entities +// declared outside the innermost enclosing namespace scope, the +// block scope declaration declares that same entity and +// receives the linkage of the previous declaration. + +// rdar://13535367 +namespace test0 { + extern "C" int test0_array[]; + void declare() { extern int test0_array[100]; } + extern "C" int test0_array[]; + int value = sizeof(test0_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +} + +namespace test1 { + extern "C" int test1_array[]; + void test() { + { extern int test1_array[100]; } + extern int test1_array[]; + int x = sizeof(test1_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + } +} + +namespace test2 { + void declare() { extern int test2_array[100]; } + extern int test2_array[]; + int value = sizeof(test2_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +} + +namespace test3 { + void test() { + { extern int test3_array[100]; } + extern int test3_array[]; + int x = sizeof(test3_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + } +} + + diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp index 7ecedd5..1f78a73 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s struct X0 { X0 f1(); X0 f2(); @@ -25,3 +26,92 @@ struct X0::X0 X0::f2() { return X0(); } template<typename T> X1<T>::X1<T> X1<T>::f2() { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}} template<typename T> X1<T>::X1<T> (X1<T>::f2)(int) { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}} template<typename T> struct X1<T>::X1<T> (X1<T>::f2)(float) { } + +// We have a special case for lookup within using-declarations that are +// member-declarations: foo::bar::baz::baz always names baz's constructor +// in such a context, even if looking up 'baz' within foo::bar::baz would +// not find the injected-class-name. Likewise foo::bar::baz<T>::baz also +// names the constructor. +namespace InhCtor { + struct A { + A(int); + protected: + int T(); + }; + typedef A T; + struct B : A { + // This is a using-declaration for 'int A::T()' in C++98, but is an + // inheriting constructor declaration in C++11. + using InhCtor::T::T; + }; +#if __cplusplus < 201103L + B b(123); // expected-error {{no matching constructor}} + // expected-note@-7 2{{candidate constructor}} + int n = b.T(); // ok, accessible +#else + B b(123); // ok, inheriting constructor + int n = b.T(); // expected-error {{'T' is a protected member of 'InhCtor::A'}} + // expected-note@-15 {{declared protected here}} + + template<typename T> + struct S : T { + struct U : S { + using S::S; + }; + using T::T; + }; + + S<A>::U ua(0); + S<B>::U ub(0); + + template<typename T> + struct X : T { + using T::Z::U::U; + }; + template<typename T> + struct X2 : T { + using T::Z::template V<int>::V; + }; + struct Y { + struct Z { + typedef Y U; + template<typename T> using V = Y; + }; + Y(int); + }; + X<Y> xy(0); + + namespace Repeat { + struct A { + struct T { + T(int); + }; + }; + struct Z : A { + using A::A::A; + }; + template<typename T> + struct ZT : T::T { + using T::T::T; + }; + } + + namespace NS { + struct NS {}; + } + struct DerivedFromNS : NS::NS { + // No special case unless the NNS names a class. + using InhCtor::NS::NS; // expected-error {{using declaration in class refers into 'InhCtor::NS::', which is not a class}} + + }; + + typedef int I; + struct UsingInt { + using I::I; // expected-error {{expected a class or namespace}} + }; + template<typename T> struct UsingIntTemplate { + using T::T; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} + }; + UsingIntTemplate<int> uit; // expected-note {{here}} +#endif +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp index 4ffe538..7da3087 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp @@ -17,3 +17,33 @@ namespace N { int i = 2; N::S N::j = i; N::S N::j2(i); + +// <rdar://problem/13317030> +namespace M { + class X { }; + inline X operator-(int, X); + + template<typename T> + class Y { }; + + typedef Y<float> YFloat; + + namespace yfloat { + YFloat operator-(YFloat, YFloat); + } + using namespace yfloat; +} + +using namespace M; + +namespace M { + +class Other { + void foo(YFloat a, YFloat b); +}; + +} + +void Other::foo(YFloat a, YFloat b) { + YFloat c = a - b; +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp index d2afd5d..9632fda 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp @@ -33,5 +33,5 @@ namespace test1 { // specifiers. namespace test2 { template <class T> struct bar {}; - template <class T> struct foo : bar<foo> {}; // expected-error {{use of class template foo requires template arguments}} expected-note {{template is declared here}} + template <class T> struct foo : bar<foo> {}; // expected-error {{use of class template 'foo' requires template arguments}} expected-note {{template is declared here}} } diff --git a/test/CXX/basic/basic.start/basic.start.main/p2.cpp b/test/CXX/basic/basic.start/basic.start.main/p2.cpp new file mode 100644 index 0000000..a5386f1 --- /dev/null +++ b/test/CXX/basic/basic.start/basic.start.main/p2.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST1 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST2 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST3 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST4 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST5 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST6 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST7 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST8 + +// RUN: cp %s %t +// RUN: %clang_cc1 -x c++ %s -std=c++11 -fsyntax-only -verify -DTEST9 +// RUN: not %clang_cc1 -x c++ %t -std=c++11 -fixit -DTEST9 +// RUN: %clang_cc1 -x c++ %t -std=c++11 -fsyntax-only -DTEST9 + +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST10 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST12 + +#if TEST1 + +// expected-no-diagnostics +typedef int Int; +typedef char Char; +typedef Char* Carp; + +Int main(Int argc, Carp argv[]) { +} + +#elif TEST2 + +// expected-no-diagnostics +typedef int Int; +typedef char Char; +typedef Char* Carp; + +Int main(Int argc, Carp argv[], Char *env[]) { +} + +#elif TEST3 + +// expected-no-diagnostics +int main() { +} + +#elif TEST4 + +static int main() { // expected-error {{'main' is not allowed to be declared static}} +} + +#elif TEST5 + +inline int main() { // expected-error {{'main' is not allowed to be declared inline}} +} + +#elif TEST6 + +void // expected-error {{'main' must return 'int'}} +main( // expected-error {{first parameter of 'main' (argument count) must be of type 'int'}} + float a +) { +} + +#elif TEST7 + +// expected-no-diagnostics +int main(int argc, const char* const* argv) { +} + +#elif TEST8 + +template<typename T> +int main() { } // expected-error{{'main' cannot be a template}} + +#elif TEST9 + +constexpr int main() { } // expected-error{{'main' is not allowed to be declared constexpr}} + +#elif TEST10 + +// PR15100 +// expected-no-diagnostics +typedef char charT; +int main(int, const charT**) {} + +#elif TEST11 + +// expected-no-diagnostics +typedef char charT; +int main(int, charT* const *) {} + +#elif TEST12 + +// expected-no-diagnostics +typedef char charT; +int main(int, const charT* const *) {} + +#else + +#error Unknown test mode + +#endif diff --git a/test/CXX/basic/basic.start/basic.start.main/p2a.cpp b/test/CXX/basic/basic.start/basic.start.main/p2a.cpp deleted file mode 100644 index b27d492..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2a.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics - -typedef int Int; -typedef char Char; -typedef Char* Carp; - -Int main(Int argc, Carp argv[]) { -} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2b.cpp b/test/CXX/basic/basic.start/basic.start.main/p2b.cpp deleted file mode 100644 index 65cd202..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2b.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics - -typedef int Int; -typedef char Char; -typedef Char* Carp; - -Int main(Int argc, Carp argv[], Char *env[]) { -} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2c.cpp b/test/CXX/basic/basic.start/basic.start.main/p2c.cpp deleted file mode 100644 index 2b082ec..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2c.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics - -int main() { -} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2d.cpp b/test/CXX/basic/basic.start/basic.start.main/p2d.cpp deleted file mode 100644 index bcdbdb2..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2d.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -static int main() { // expected-error {{'main' is not allowed to be declared static}} -} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2e.cpp b/test/CXX/basic/basic.start/basic.start.main/p2e.cpp deleted file mode 100644 index 954fdbd..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2e.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -inline int main() { // expected-error {{'main' is not allowed to be declared inline}} -} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2f.cpp b/test/CXX/basic/basic.start/basic.start.main/p2f.cpp deleted file mode 100644 index ea5a752..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2f.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -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/p2g.cpp b/test/CXX/basic/basic.start/basic.start.main/p2g.cpp deleted file mode 100644 index 45f643f..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2g.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics - -int main(int argc, const char* const* argv) { -} diff --git a/test/CXX/basic/basic.start/basic.start.main/p2h.cpp b/test/CXX/basic/basic.start/basic.start.main/p2h.cpp deleted file mode 100644 index abf8faa..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2h.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -template<typename T> -int main() { } // expected-error{{'main' cannot be a template}} - diff --git a/test/CXX/basic/basic.start/basic.start.main/p2i.cpp b/test/CXX/basic/basic.start/basic.start.main/p2i.cpp deleted file mode 100644 index db8da3c..0000000 --- a/test/CXX/basic/basic.start/basic.start.main/p2i.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// 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 191d42b..6401c29 100644 --- a/test/CXX/basic/basic.types/p10.cpp +++ b/test/CXX/basic/basic.types/p10.cpp @@ -39,7 +39,7 @@ struct UserProvDtor { struct NonTrivDtor { 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}} + virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}} }; struct NonTrivDtorBase { ~NonTrivDtorBase(); diff --git a/test/CXX/class.access/class.access.base/p5.cpp b/test/CXX/class.access/class.access.base/p5.cpp index 255fbfc..5b08a86 100644 --- a/test/CXX/class.access/class.access.base/p5.cpp +++ b/test/CXX/class.access/class.access.base/p5.cpp @@ -72,4 +72,27 @@ namespace test3 { }; } +// Don't crash. <rdar://12926092> +// Note that 'field' is indeed a private member of X but that access +// is indeed ultimately constrained by the protected inheritance from Y. +// If someone wants to put the effort into improving this diagnostic, +// they can feel free; even explaining it in person would be a pain. +namespace test4 { + class Z; + class X { + public: + void f(Z *p); + + private: + int field; // expected-note {{member is declared here}} + }; + + class Y : public X { }; + class Z : protected Y { }; // expected-note 2 {{constrained by protected inheritance here}} + + void X::f(Z *p) { + p->field = 0; // expected-error {{cannot cast 'test4::Z' to its protected base class 'test4::X'}} expected-error {{'field' is a private member of 'test4::X'}} + } +} + // TODO: flesh out these cases diff --git a/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/test/CXX/class.access/class.friend/p3-cxx0x.cpp index e4d5fd5..ea9d2ce 100644 --- a/test/CXX/class.access/class.friend/p3-cxx0x.cpp +++ b/test/CXX/class.access/class.friend/p3-cxx0x.cpp @@ -28,14 +28,19 @@ X1<Y2> x1a; X1<Y3> x1b; X1<Y1> x1c; // expected-note{{in instantiation of template class 'X1<Y1>' requested here}} +template<typename T> class B; + template<typename T> class A { T x; public: class foo {}; static int y; + template <typename S> friend class B<S>::ty; }; +template <typename T> class B { typedef int ty; }; + struct { // Ill-formed int friend; // expected-error {{'friend' must appear first in a non-function declaration}} @@ -53,3 +58,5 @@ struct { float; template<typename T> friend class A<T>::foo; } a; + +void testA() { (void)sizeof(A<int>); } diff --git a/test/CXX/class.access/class.protected/p1.cpp b/test/CXX/class.access/class.protected/p1.cpp index 132ff61..825447e 100644 --- a/test/CXX/class.access/class.protected/p1.cpp +++ b/test/CXX/class.access/class.protected/p1.cpp @@ -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 {{can only access this member on an object of type}} expected-note {{member is declared here}} + protected: int foo(); // expected-note 4 {{declared}} expected-note 3 {{can only access this member on an object of type}} expected-note 2 {{member is declared here}} }; class B : public A { // expected-note {{member is declared here}} @@ -344,14 +344,15 @@ namespace test9 { static void test(A &a) { a.foo(); // expected-error {{'foo' is a protected member}} a.A::foo(); // expected-error {{'foo' is a protected member}} - a.B::foo(); + a.B::foo(); // expected-error {{'foo' is a protected member}} a.C::foo(); // expected-error {{'foo' is a protected member}} + a.D::foo(); // expected-error {{'foo' is a protected member}} } static void test(B &b) { b.foo(); b.A::foo(); - b.B::foo(); + b.B::foo(); // accessible as named in A b.C::foo(); // expected-error {{'foo' is a protected member}} } diff --git a/test/CXX/class.derived/class.abstract/p16.cpp b/test/CXX/class.derived/class.abstract/p16.cpp index 93f905c..c237ed9 100644 --- a/test/CXX/class.derived/class.abstract/p16.cpp +++ b/test/CXX/class.derived/class.abstract/p16.cpp @@ -14,3 +14,29 @@ struct C: A { virtual void a(); virtual void b() = delete; }; + +struct E; +struct F; +struct G; +struct H; +struct D { + virtual E &operator=(const E &); // expected-note {{here}} + virtual F &operator=(const F &); + virtual G &operator=(G&&); + virtual H &operator=(H&&); // expected-note {{here}} + friend struct F; + +private: + D &operator=(const D&) = default; + D &operator=(D&&) = default; + virtual ~D(); // expected-note 2{{here}} +}; +struct E : D {}; // expected-error {{deleted function '~E' cannot override a non-deleted function}} \ + // expected-error {{deleted function 'operator=' cannot override a non-deleted function}} +struct F : D {}; +// No move ctor here, because it would be deleted. +struct G : D {}; // expected-error {{deleted function '~G' cannot override a non-deleted function}} +struct H : D { + H &operator=(H&&) = default; // expected-error {{deleted function 'operator=' cannot override a non-deleted function}} + ~H(); +}; diff --git a/test/CXX/class.derived/class.virtual/p3-0x.cpp b/test/CXX/class.derived/class.virtual/p3-0x.cpp index 16f9828..6a02a86 100644 --- a/test/CXX/class.derived/class.virtual/p3-0x.cpp +++ b/test/CXX/class.derived/class.virtual/p3-0x.cpp @@ -100,3 +100,33 @@ namespace PR13499 { Y<X> y; Z<X> z; // expected-note {{in instantiation of}} } + +namespace MemberOfUnknownSpecialization { + template<typename T> struct A { + struct B {}; + struct C : B { + void f() override; + }; + }; + + template<> struct A<int>::B { + virtual void f(); + }; + // ok + A<int>::C c1; + + template<> struct A<char>::B { + void f(); + }; + // expected-error@-13 {{only virtual member functions can be marked 'override'}} + // expected-note@+1 {{in instantiation of}} + A<char>::C c2; + + template<> struct A<double>::B { + virtual void f() final; + }; + // expected-error@-20 {{declaration of 'f' overrides a 'final' function}} + // expected-note@-3 {{here}} + // expected-note@+1 {{in instantiation of}} + A<double>::C c3; +} 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 117997e..1607bac 100644 --- a/test/CXX/class/class.static/class.static.data/p3.cpp +++ b/test/CXX/class/class.static/class.static.data/p3.cpp @@ -13,7 +13,7 @@ struct S { static const int d2 = 0; static constexpr double e = 0.0; // ok - static const double f = 0.0; // expected-warning {{extension}} expected-note {{use 'constexpr' specifier}} + static const double f = 0.0; // expected-error {{requires 'constexpr' specifier}} expected-note {{add 'constexpr'}} static char *const g = 0; // expected-error {{requires 'constexpr' specifier}} static const NonLit h = NonLit(); // expected-error {{must be initialized out of line}} }; diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp index ee97410..439cc9c 100644 --- a/test/CXX/class/class.union/p1.cpp +++ b/test/CXX/class/class.union/p1.cpp @@ -14,25 +14,25 @@ class VirtualBase : virtual Okay { // expected-note 4 {{because type 'VirtualBas }; class Ctor { - Ctor() { abort(); } // expected-note 4 {{because type 'Ctor' has a user-declared constructor}} + Ctor() { abort(); } // expected-note 2{{because type 'Ctor' has a user-provided default constructor}} expected-note 2{{here}} }; class Ctor2 { - Ctor2(); // expected-note 3 {{because type 'Ctor2' has a user-declared constructor}} + Ctor2(); // expected-note {{because type 'Ctor2' has a user-provided default constructor}} expected-note 2{{here}} }; -class CtorTmpl { - template<typename T> CtorTmpl(); // expected-note {{because type 'CtorTmpl' has a user-declared constructor}} +class CtorTmpl { // expected-note {{because type 'CtorTmpl' has no default constructor}} + template<typename T> CtorTmpl(); // expected-note {{implicit default constructor suppressed by user-declared constructor}} }; -class CopyCtor { - CopyCtor(CopyCtor &cc) { abort(); } // expected-note 4 {{because type 'CopyCtor' has a user-declared copy constructor}} +class CopyCtor { // expected-note 2{{because no constructor can be used to copy an object of type 'const CopyCtor'}} + CopyCtor(CopyCtor &cc) { abort(); } }; -class CopyAssign { - CopyAssign& operator=(CopyAssign& CA) { abort(); } // expected-note 4 {{because type 'CopyAssign' has a user-declared copy assignment operator}} +class CopyAssign { // expected-note 2 {{because no assignment operator can be used to copy an object of type 'const CopyAssign'}} + CopyAssign& operator=(CopyAssign& CA) { abort(); } }; class Dtor { - ~Dtor() { abort(); } // expected-note 4 {{because type 'Dtor' has a user-declared destructor}} + ~Dtor() { abort(); } // expected-note 2 {{because type 'Dtor' has a user-provided destructor}} expected-note 2{{here}} }; union U1 { @@ -49,25 +49,25 @@ union U1 { union U2 { struct { - Virtual v; // expected-note {{because type 'U2::<anonymous struct}} + Virtual v; // expected-note {{because the function selected to copy field of type 'Virtual' is not trivial}} } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} struct { - VirtualBase vbase; // expected-note {{because type 'U2::<anonymous struct}} + VirtualBase vbase; // expected-note {{because the function selected to copy field of type 'VirtualBase' is not trivial}} } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} struct { - Ctor ctor; // expected-note {{because type 'U2::<anonymous struct}} + Ctor ctor; // expected-note {{because field of type 'Ctor' has a user-provided default constructor}} } m3; // expected-error {{union member 'm3' has a non-trivial constructor}} struct { - Ctor2 ctor2; // expected-note {{because type 'U2::<anonymous struct}} + Ctor2 ctor2; // expected-note {{because field of type 'Ctor2' has a user-provided default constructor}} } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} - struct { - CopyCtor copyctor; // expected-note {{because type 'U2::<anonymous struct}} + struct { // expected-note {{no constructor can be used to copy an object of type 'const}} + CopyCtor copyctor; } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} - struct { - CopyAssign copyassign; // expected-note {{because type 'U2::<anonymous struct}} + struct { // expected-note {{no assignment operator can be used to copy an object of type 'const}} + CopyAssign copyassign; } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} struct { - Dtor dtor; // expected-note {{because type 'U2::<anonymous struct}} + Dtor dtor; // expected-note {{because field of type 'Dtor' has a user-provided destructor}} } m6; // expected-error {{union member 'm6' has a non-trivial destructor}} struct { Okay okay; @@ -75,22 +75,25 @@ union U2 { }; union U3 { - struct s1 : Virtual { // expected-note {{because type 'U3::s1' has a base class with a non-trivial copy constructor}} + struct s1 : Virtual { // expected-note {{because the function selected to copy base class of type 'Virtual' is not trivial}} } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} - struct s2 : VirtualBase { // expected-note {{because type 'U3::s2' has a base class with a non-trivial copy constructor}} + struct s2 : VirtualBase { // expected-note {{because the function selected to copy base class of type 'VirtualBase' is not trivial}} } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} - struct s3 : Ctor { // expected-note {{because type 'U3::s3' has a base class with a non-trivial constructor}} + struct s3 : Ctor { // expected-note {{because base class of type 'Ctor' has a user-provided default constructor}} } m3; // expected-error {{union member 'm3' has a non-trivial constructor}} - struct s3a : Ctor2 { // expected-note {{because type 'U3::s3a' has a base class with a non-trivial constructor}} + struct s3a : Ctor2 { // expected-note {{because base class of type 'Ctor2' has a user-provided default constructor}} } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} - struct s4 : CopyCtor { // expected-note {{because type 'U3::s4' has a base class with a non-trivial copy constructor}} + struct s4 : CopyCtor { // expected-note {{because no constructor can be used to copy an object of type 'const U3::s4'}} } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} - struct s5 : CopyAssign { // expected-note {{because type 'U3::s5' has a base class with a non-trivial copy assignment operator}} + struct s5 : CopyAssign { // expected-note {{because no assignment operator can be used to copy an object of type 'const U3::s5'}} } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} - struct s6 : Dtor { // expected-note {{because type 'U3::s6' has a base class with a non-trivial destructor}} + struct s6 : Dtor { // expected-note {{because base class of type 'Dtor' has a user-provided destructor}} } m6; // expected-error {{union member 'm6' has a non-trivial destructor}} struct s7 : Okay { } m7; + struct s8 { + s8(...) = delete; // expected-note {{because it is a variadic function}} expected-warning {{C++11}} + } m8; // expected-error {{union member 'm8' has a non-trivial constructor}} }; union U4 { @@ -102,6 +105,12 @@ union U5 { int& i1; // expected-error {{union member 'i1' has reference type 'int &'}} }; +union U6 { + struct S { + int &i; + } s; // ok +}; + template <class A, class B> struct Either { bool tag; union { // expected-note 6 {{in instantiation of member class}} diff --git a/test/CXX/class/class.union/p2-0x.cpp b/test/CXX/class/class.union/p2-0x.cpp index b5c4109..5fb8a67 100644 --- a/test/CXX/class/class.union/p2-0x.cpp +++ b/test/CXX/class/class.union/p2-0x.cpp @@ -7,7 +7,7 @@ union U1 { 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'}} + static const double k5 = k4; // expected-error {{requires 'constexpr' specifier}} expected-note {{add 'constexpr'}} int n[k1 + 3]; }; diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp index 069ca0a..11372dd 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -91,3 +91,104 @@ namespace test5 { template void f<int>(int); template void f<long>(long); //expected-note {{instantiation}} } + +// rdar://13393749 +namespace test6 { + class A; + namespace ns { + class B { + static void foo(); // expected-note {{implicitly declared private here}} + friend union A; + }; + + union A { + void test() { + B::foo(); + } + }; + } + + class A { + void test() { + ns::B::foo(); // expected-error {{'foo' is a private member of 'test6::ns::B'}} + } + }; +} + +// We seem to be following a correct interpretation with these, but +// the standard could probably be a bit clearer. +namespace test7a { + namespace ns { + class A; + } + + using namespace ns; + class B { + static void foo(); + friend class A; + }; + + class ns::A { + void test() { + B::foo(); + } + }; +} +namespace test7b { + namespace ns { + class A; + } + + using ns::A; + class B { + static void foo(); + friend class A; + }; + + class ns::A { + void test() { + B::foo(); + } + }; +} +namespace test7c { + namespace ns1 { + class A; + } + + namespace ns2 { + // ns1::A appears as if declared in test7c according to [namespace.udir]p2. + // I think that means we aren't supposed to find it. + using namespace ns1; + class B { + static void foo(); // expected-note {{implicitly declared private here}} + friend class A; + }; + } + + class ns1::A { + void test() { + ns2::B::foo(); // expected-error {{'foo' is a private member of 'test7c::ns2::B'}} + } + }; +} +namespace test7d { + namespace ns1 { + class A; + } + + namespace ns2 { + // Honor the lexical context of a using-declaration, though. + using ns1::A; + class B { + static void foo(); + friend class A; + }; + } + + class ns1::A { + void test() { + ns2::B::foo(); + } + }; +} diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp index ae40062..a38ff15 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp @@ -33,3 +33,12 @@ namespace test1 { } } +// PR 14768 +namespace PR14768 { + template<typename eT> class Mat; + template<typename eT> class Col : public Mat<eT> { + using Mat<eT>::operator(); + using Col<eT>::operator(); + void operator() (); + }; +} diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp new file mode 100644 index 0000000..10be98d --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -verify %s + +alignas(1) int n1; // expected-error {{requested alignment is less than minimum alignment of 4 for type 'int'}} +alignas(1) alignas(2) int n2; // expected-error {{less than minimum alignment}} +alignas(1) alignas(2) alignas(4) int n3; // ok +alignas(1) alignas(2) alignas(0) int n4; // expected-error {{less than minimum alignment}} +alignas(1) alignas(2) int n5 alignas(4); // ok +alignas(1) alignas(4) int n6 alignas(2); // ok +alignas(1) int n7 alignas(2), // expected-error {{less than minimum alignment}} + n8 alignas(4); // ok +alignas(8) int n9 alignas(2); // ok, overaligned + +enum alignas(1) E1 {}; // expected-error {{requested alignment is less than minimum alignment of 4 for type 'E1'}} +enum alignas(1) E2 : char {}; // ok +enum alignas(4) E3 { e3 = 0 }; // ok +enum alignas(4) E4 { e4 = 1ull << 33 }; // expected-error {{requested alignment is less than minimum alignment of 8 for type 'E4'}} + +struct S1 { + alignas(8) int n; +}; +struct alignas(2) S2 { // expected-error {{requested alignment is less than minimum alignment of 4 for type 'S2'}} + int n; +}; +struct alignas(2) S3 { // expected-error {{requested alignment is less than minimum alignment of 8 for type 'S3'}} + S1 s1; +}; +struct alignas(2) S4 : S1 { // expected-error {{requested alignment is less than minimum alignment of 8 for type 'S4'}} +}; +struct S5 : S1 { + alignas(2) S1 s1; // expected-error {{requested alignment is less than minimum alignment of 8 for type 'S1'}} +}; +struct S6 { + S1 s1; +}; +struct S7 : S1 { +}; +struct alignas(2) alignas(8) alignas(1) S8 : S1 { +}; + +S1 s1 alignas(4); // expected-error {{requested alignment is less than minimum alignment of 8 for type 'S1'}} +S6 s6 alignas(4); // expected-error {{requested alignment is less than minimum alignment of 8 for type 'S6'}} +S7 s7 alignas(4); // expected-error {{requested alignment is less than minimum alignment of 8 for type 'S7'}} + +template<int N, int M, typename T> +struct alignas(N) X { // expected-error 3{{requested alignment is less than minimum}} + alignas(M) T t; // expected-error 3{{requested alignment is less than minimum}} +}; + +template struct X<1, 1, char>; +template struct X<4, 1, char>; +template struct X<1, 2, char>; // expected-note {{instantiation}} +template struct X<1, 1, short>; // expected-note {{instantiation}} +template struct X<2, 1, short>; // expected-note {{instantiation}} +template struct X<2, 2, short>; +template struct X<16, 8, S1>; +template struct X<4, 4, S1>; // expected-note {{instantiation}} + +template<int N, typename T> +struct Y { + enum alignas(N) E : T {}; // expected-error {{requested alignment is less than minimum}} +}; +template struct Y<1, char>; +template struct Y<2, char>; +template struct Y<1, short>; // expected-note {{instantiation}} +template struct Y<2, short>; + +template<int N, typename T> +void f() { + alignas(N) T v; // expected-error {{requested alignment is less than minimum}} +}; +template void f<1, char>(); +template void f<2, char>(); +template void f<1, short>(); // expected-note {{instantiation}} +template void f<2, short>(); diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp new file mode 100644 index 0000000..e788577 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +alignas(4) extern int n1; // expected-note {{previous declaration}} +alignas(8) int n1; // expected-error {{redeclaration has different alignment requirement (8 vs 4)}} + +alignas(8) int n2; // expected-note {{previous declaration}} +alignas(4) extern int n2; // expected-error {{different alignment requirement (4 vs 8)}} + +alignas(8) extern int n3; // expected-note {{previous declaration}} +alignas(4) extern int n3; // expected-error {{different alignment requirement (4 vs 8)}} + +extern int n4; +alignas(8) extern int n4; + +alignas(8) extern int n5; +extern int n5; + +int n6; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} +alignas(8) extern int n6; // expected-note {{declared with 'alignas' attribute here}} + +extern int n7; +alignas(8) int n7; + +alignas(8) extern int n8; // expected-note {{declared with 'alignas' attribute here}} +int n8; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} + +int n9; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} +alignas(4) extern int n9; // expected-note {{declared with 'alignas' attribute here}} + + +enum alignas(2) E : char; // expected-note {{declared with 'alignas' attribute here}} +enum E : char {}; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} + +enum alignas(4) F : char; // expected-note {{previous declaration is here}} +enum alignas(2) F : char; // expected-error {{redeclaration has different alignment requirement (2 vs 4)}} + +enum G : char; +enum alignas(8) G : char {}; +enum G : char; + +enum H : char {}; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} +enum alignas(1) H : char; // expected-note {{declared with 'alignas' attribute here}} + + +struct S; +struct alignas(16) S; // expected-note {{declared with 'alignas' attribute here}} +struct S; +struct S { int n; }; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} + +struct alignas(2) T; +struct alignas(2) T { char c; }; // expected-note {{previous declaration is here}} +struct T; +struct alignas(4) T; // expected-error {{redeclaration has different alignment requirement (4 vs 2)}} + +struct U; +struct alignas(2) U {}; + +struct V {}; // expected-error {{'alignas' must be specified on definition if it is specified on any declaration}} +struct alignas(1) V; // expected-note {{declared with 'alignas' attribute here}} + +template<int M, int N> struct alignas(M) W; +template<int M, int N> struct alignas(N) W {}; +W<4,4> w44; // ok +// FIXME: We should reject this. +W<1,2> w12; +static_assert(alignof(W<4,4>) == 4, ""); + +template<int M, int N, int O, int P> struct X { + alignas(M) alignas(N) static char Buffer[32]; // expected-note {{previous declaration is here}} +}; +template<int M, int N, int O, int P> +alignas(O) alignas(P) char X<M, N, O, P>::Buffer[32]; // expected-error {{redeclaration has different alignment requirement (8 vs 2)}} +char *x1848 = X<1,8,4,8>::Buffer; // ok +char *x1248 = X<1,2,4,8>::Buffer; // expected-note {{in instantiation of}} + +template<int M, int N, int O, int P> struct Y { + enum alignas(M) alignas(N) E : char; +}; +template<int M, int N, int O, int P> +enum alignas(O) alignas(P) Y<M,N,O,P>::E : char { e }; +int y1848 = Y<1,8,4,8>::e; +// FIXME: We should reject this. +int y1248 = Y<1,2,4,8>::e; + +// Don't crash here. +alignas(4) struct Incomplete incomplete; // expected-error {{incomplete type}} expected-note {{forward declaration}} diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp new file mode 100644 index 0000000..93b1c64 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<typename T, typename A, int N> struct X { + alignas(T) alignas(A) T buffer[N]; +}; + +static_assert(alignof(X<char, int, sizeof(int)>) == alignof(int), ""); +static_assert(alignof(X<int, char, 1>) == alignof(int), ""); + + +template<typename T, typename A, int N> struct Y { + alignas(A) T buffer[N]; // expected-error {{requested alignment is less than minimum alignment of 4 for type 'int [1]'}} +}; + +static_assert(alignof(Y<char, int, sizeof(int)>) == alignof(int), ""); +static_assert(alignof(Y<int, char, 1>) == alignof(int), ""); // expected-note {{in instantiation of}} diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp new file mode 100644 index 0000000..686aac2 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +alignas(double) void f(); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} +alignas(double) unsigned char c[sizeof(double)]; // expected-note {{previous}} +extern unsigned char c[sizeof(double)]; +alignas(float) extern unsigned char c[sizeof(double)]; // expected-error {{different alignment}} diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p1.cpp new file mode 100644 index 0000000..9f7ef3a --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +[[carries_dependency, carries_dependency]] int m1(); // expected-error {{attribute 'carries_dependency' cannot appear multiple times in an attribute specifier}} +[[carries_dependency]] [[carries_dependency]] int m2(); // ok +[[carries_dependency()]] int m3(); // expected-error {{attribute 'carries_dependency' cannot have an argument list}} + +[[carries_dependency]] void f1(); // FIXME: warn here +[[carries_dependency]] int f2(); // ok +int f3(int param [[carries_dependency]]); // ok +[[carries_dependency]] int (*f4)(); // expected-error {{'carries_dependency' attribute only applies to functions, methods, and parameters}} +int (*f5 [[carries_dependency]])(); // expected-error {{'carries_dependency' attribute only applies to functions, methods, and parameters}} +int (*f6)() [[carries_dependency]]; // expected-error {{'carries_dependency' attribute cannot be applied to types}} +int (*f7)(int n [[carries_dependency]]); // expected-error {{'[[carries_dependency]]' attribute only allowed on parameter in a function declaration}} +int (((f8)))(int n [[carries_dependency]]); // ok +int (*f9(int n))(int n [[carries_dependency]]); // expected-error {{'[[carries_dependency]]' attribute only allowed on parameter in a function declaration}} +int typedef f10(int n [[carries_dependency]]); // expected-error {{'[[carries_dependency]]' attribute only allowed on parameter in a function declaration}} +using T = int(int n [[carries_dependency]]); // expected-error {{'[[carries_dependency]]' attribute only allowed on parameter in a function declaration}} +struct S { + [[carries_dependency]] int f(int n [[carries_dependency]]); // ok + int (*p)(int n [[carries_dependency]]); // expected-error {{'[[carries_dependency]]' attribute only allowed on parameter in a function declaration}} +}; +void f() { + [[carries_dependency]] int f(int n [[carries_dependency]]); // ok + [[carries_dependency]] // expected-error {{'carries_dependency' attribute only applies to functions, methods, and parameters}} + int (*p)(int n [[carries_dependency]]); // expected-error {{'[[carries_dependency]]' attribute only allowed on parameter in a function declaration}} +} + +auto l1 = [](int n [[carries_dependency]]) {}; +// There's no way to write a lambda such that the return value carries +// a dependency, because an attribute applied to the lambda appertains to +// the *type* of the operator() function, not to the function itself. +auto l2 = []() [[carries_dependency]] {}; // expected-error {{'carries_dependency' attribute cannot be applied to types}} diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p2.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p2.cpp new file mode 100644 index 0000000..d5b0ebf --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.depend/p2.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +int f(int); // expected-note 2{{declaration missing '[[carries_dependency]]' attribute is here}} +[[carries_dependency]] int f(int); // expected-error {{function declared '[[carries_dependency]]' after its first declaration}} +int f(int n [[carries_dependency]]); // expected-error {{parameter declared '[[carries_dependency]]' after its first declaration}} + +int g([[carries_dependency]] int n); // expected-note {{declaration missing '[[carries_dependency]]' attribute is here}} +int g(int); +[[carries_dependency]] int g(int); // expected-error {{function declared '[[carries_dependency]]' after its first declaration}} +int g(int n [[carries_dependency]]); + +int h [[carries_dependency]](); +int h(); +[[carries_dependency]] int h(); diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp new file mode 100644 index 0000000..0af241f --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fcxx-exceptions %s + +[[noreturn]] void a() { + return; // expected-warning {{function 'a' declared 'noreturn' should not return}} +} +void a2 [[noreturn]] () { + return; // expected-warning {{function 'a2' declared 'noreturn' should not return}} +} + +[[noreturn, noreturn]] void b() { throw 0; } // expected-error {{attribute 'noreturn' cannot appear multiple times in an attribute specifier}} +[[noreturn]] [[noreturn]] void b2() { throw 0; } // ok + +[[noreturn()]] void c(); // expected-error {{attribute 'noreturn' cannot have an argument list}} + +void d() [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to types}} +int d2 [[noreturn]]; // expected-error {{'noreturn' attribute only applies to functions and methods}} + +[[noreturn]] int e() { b2(); } // ok + +int f(); // expected-note {{declaration missing '[[noreturn]]' attribute is here}} +[[noreturn]] int f(); // expected-error {{function declared '[[noreturn]]' after its first declaration}} +int f(); + +[[noreturn]] int g(); +int g() { while (true) b(); } // ok +[[noreturn]] int g(); + +[[gnu::noreturn]] int h(); + +template<typename T> void test_type(T) { T::error; } // expected-error {{has no members}} +template<> void test_type(int (*)()) {} + +void check() { + // We do not consider [[noreturn]] to be part of the function's type. + // However, we do treat [[gnu::noreturn]] as being part of the type. + // + // This isn't quite GCC-compatible; it treats [[gnu::noreturn]] as + // being part of a function *pointer* type, but not being part of + // a function type. + test_type(e); + test_type(f); + test_type(g); + test_type(h); // expected-note {{instantiation}} +} 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 6820fc6..a3a964a 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -25,8 +25,9 @@ constexpr notlit nl1; // expected-error {{constexpr variable cannot have non-lit void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}} // non-static member struct s2 { - constexpr int mi1; // expected-error {{non-static data member cannot be constexpr}} + constexpr int mi1; // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}} static constexpr int mi2; // expected-error {{requires an initializer}} + mutable constexpr int mi3 = 3; // expected-error-re {{non-static data member cannot be constexpr$}} expected-error {{'mutable' and 'const' cannot be mixed}} }; // typedef typedef constexpr int CI; // expected-error {{typedef cannot be constexpr}} 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 dfc1d3d..ad156c8 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -272,9 +272,8 @@ namespace CtorLookup { struct A { constexpr A(const A&) {} A(A&) {} - constexpr A(int); // expected-note {{previous}} + constexpr A(int = 0); }; - constexpr A::A(int = 0) {} // expected-warning {{default constructor}} struct B : A { B() = default; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp index 3c1152c..bca73ee 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -verify -std=c++11 -fcxx-exceptions %s -// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s -DNO_INVALID_CONSTEXPR namespace StdExample { @@ -110,3 +110,23 @@ int y1 = Y<int>().get(); // ok int y2 = Y<Z>().get(); // ok } + +#ifndef NO_INVALID_CONSTEXPR +namespace PR14550 { + // As an "extension", we allow functions which can't produce constant + // expressions to be declared constexpr in system headers (libstdc++ + // marks some functions as constexpr which use builtins which we don't + // support constant folding). Ensure that we don't mark those functions + // as invalid after suppressing the diagnostic. +# 122 "p5.cpp" 1 3 + int n; + struct A { + static constexpr int f() { return n; } + }; + template<typename T> struct B { + B() { g(T::f()); } // expected-error {{undeclared identifier 'g'}} + }; +# 130 "p5.cpp" 2 + template class B<A>; // expected-note {{here}} +} +#endif 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 c4935b3..344f8ce 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp @@ -1,19 +1,39 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +using size_t = decltype(sizeof(int)); + struct S { constexpr int f(); constexpr int g() const; + constexpr int h(); + int h(); static constexpr int Sf(); + /*static*/ constexpr void *operator new(size_t) noexcept; + template<typename T> constexpr T tm(); + template<typename T> static constexpr T ts(); }; void f(const S &s) { s.f(); s.g(); - int (*f)() = &S::Sf; + int (*Sf)() = &S::Sf; + int (S::*f)() const = &S::f; int (S::*g)() const = &S::g; + void *(*opNew)(size_t) = &S::operator new; + int (S::*tm)() const = &S::tm; + int (*ts)() = &S::ts; } +constexpr int S::f() const { return 0; } +constexpr int S::g() { return 1; } +constexpr int S::h() { return 0; } +int S::h() { return 0; } +constexpr int S::Sf() { return 2; } +constexpr void *S::operator new(size_t) noexcept { return 0; } +template<typename T> constexpr T S::tm() { return T(); } +template<typename T> constexpr T S::ts() { return T(); } + namespace std_example { class debug_flag { // expected-note {{not an aggregate and has no constexpr constructors}} diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp new file mode 100644 index 0000000..5199330 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -verify %s -std=c++11 + +// A function that is explicitly defaulted shall +struct A { + // -- be a special member function, + A(int) = default; // expected-error {{only special member functions may be defaulted}} + + // -- have the same declared function type as if it had been implicitly + // declared + void operator=(const A &) = default; // expected-error {{must return 'A &'}} + A(...) = default; // expected-error {{cannot be variadic}} + A(const A &, ...) = default; // expected-error {{cannot be variadic}} + + // (except for possibly differing ref-qualifiers + A &operator=(A &&) & = default; + + // and except that in the case of a copy constructor or copy assignment + // operator, the parameter type may be "reference to non-const T") + A(A &) = default; + A &operator=(A &) = default; + + // -- not have default arguments + A(double = 0.0) = default; // expected-error {{cannot have default arguments}} + A(const A & = 0) = default; // expected-error {{cannot have default arguments}} +}; diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp index 3450003..d61f6e3 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp @@ -21,7 +21,7 @@ namespace std { }; } -namespace bullet2 { +namespace bullet1 { double ad[] = { 1, 2.0 }; int ai[] = { 1, 2.0 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} @@ -62,12 +62,16 @@ namespace bullet4_example3 { }; S s1 = { 1, 2, 3.0 }; - // FIXME: This is an ill-formed narrowing initialization. - S s2 { 1.0, 2, 3 }; + S s2 { 1.0, 2, 3 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} S s3 {}; } namespace bullet5 { + int x1 {2}; + int x2 {2.0}; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} +} + +namespace bullet6 { struct S { S(std::initializer_list<double>) {} S(const std::string &) {} @@ -75,17 +79,12 @@ namespace bullet5 { const S& r1 = { 1, 2, 3.0 }; const S& r2 = { "Spinach" }; - S& r3 = { 1, 2, 3 }; // expected-error {{non-const lvalue reference to type 'bullet5::S' cannot bind to an initializer list temporary}} + S& r3 = { 1, 2, 3 }; // expected-error {{non-const lvalue reference to type 'bullet6::S' cannot bind to an initializer list temporary}} const int& i1 = { 1 }; const int& i2 = { 1.1 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} expected-warning {{implicit conversion}} const int (&iar)[2] = { 1, 2 }; } -namespace bullet6 { - int x1 {2}; - int x2 {2.0}; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} -} - namespace bullet7 { int** pp {}; } @@ -99,15 +98,25 @@ namespace bullet8 { B(std::initializer_list<int> i) {} }; B b1 { 1, 2 }; - B b2 { 1, 2.0 }; + B b2 { 1, 2.0 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} struct C { C(int i, double j) {} }; C c1 = { 1, 2.2 }; - // FIXME: This is an ill-formed narrowing initialization. - C c2 = { 1.1, 2 }; // expected-warning {{implicit conversion}} + // FIXME: Suppress the narrowing warning in the cases where we issue a narrowing error. + C c2 = { 1.1, 2 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} expected-warning {{implicit conversion}} int j { 1 }; int k { }; } + +namespace rdar13395022 { + struct MoveOnly { + MoveOnly(MoveOnly&&); // expected-note{{copy constructor is implicitly deleted because 'MoveOnly' has a user-declared move constructor}} + }; + + void test(MoveOnly mo) { + auto &&list = {mo}; // expected-error{{call to implicitly-deleted copy constructor of 'rdar13395022::MoveOnly'}} + } +} 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 adbdff6..812d0de 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 @@ -192,3 +192,11 @@ namespace PR11003 { Value y(Move(0)); } } + +namespace rdar13278115 { + struct X { }; + struct Y : X { }; + X &&f0(X &x) { return x; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::X'}} + X &&f1(Y &y) { return y; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}} + const X &&f2(Y &y) { return y; } // expected-error{{rvalue reference to type 'const rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}} +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp index 08d9639..be1113d 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -3,10 +3,10 @@ // CHECK: example0 void example0() { double d = 2.0; - // CHECK: double &rd = + // CHECK: VarDecl{{.*}}rd 'double &' // CHECK-NEXT: DeclRefExpr double &rd = d; - // CHECK: const double &rcd = + // CHECK: VarDecl{{.*}}rcd 'const double &' // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp> const double &rcd = d; } @@ -16,10 +16,10 @@ struct B : A { } b; // CHECK: example1 void example1() { - // CHECK: A &ra = + // CHECK: VarDecl{{.*}}ra 'struct A &' // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> A &ra = b; - // CHECK: const A &rca = + // CHECK: VarDecl{{.*}}rca 'const struct A &' // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> const A& rca = b; @@ -33,12 +33,12 @@ struct X { // CHECK: example2 void example2() { - // CHECK: const A &rca = + // CHECK: VarDecl{{.*}}rca 'const struct A &' // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> // CHECK: CallExpr{{.*}}B const A &rca = f(); - // CHECK: const A &r = + // CHECK: VarDecl{{.*}}r 'const struct A &' // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> // CHECK: CXXMemberCallExpr{{.*}}'struct B' @@ -47,7 +47,7 @@ void example2() { // CHECK: example3 void example3() { - // CHECK: const double &rcd2 = + // CHECK: VarDecl{{.*}}rcd2 'const double &' // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating> const double& rcd2 = 2; } diff --git a/test/CXX/dcl.decl/dcl.init/p5.cpp b/test/CXX/dcl.decl/dcl.init/p5.cpp index b50e8d7..e7ccb2e 100644 --- a/test/CXX/dcl.decl/dcl.init/p5.cpp +++ b/test/CXX/dcl.decl/dcl.init/p5.cpp @@ -1,20 +1,48 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// FIXME: Very incomplete! - // A program that calls for default-initialization or value-initialization of // an entity of reference type is illformed. If T is a cv-qualified type, the // cv-unqualified version of T is used for these definitions of // zero-initialization, default-initialization, and value-initialization. -// -// FIXME: The diagnostics for these errors are terrible because they fall out -// of the AST representation rather than being explicitly issued during the -// respective initialization forms. -struct S { // expected-error {{implicit default constructor for 'S' must explicitly initialize the reference member}} \ - // expected-note {{candidate constructor (the implicit copy constructor) not viable}} - int& x; // expected-note {{declared here}} + +struct S { // expected-error {{implicit default constructor for 'S' must explicitly initialize the reference member}} + int &x; // expected-note {{declared here}} expected-error 3{{reference to type 'int' requires an initializer}} }; S s; // expected-note {{implicit default constructor for 'S' first required here}} S f() { - return S(); // expected-error {{no matching constructor for initialization of 'S'}} + return S(); // expected-note {{in value-initialization of type 'S' here}} } + +struct T + : S { // expected-note 2{{in value-initialization of type 'S' here}} +}; +T t = T(); // expected-note {{in value-initialization of type 'T' here}} + +struct U { + T t[3]; // expected-note {{in value-initialization of type 'T' here}} +}; +U u = U(); // expected-note {{in value-initialization of type 'U' here}} + +// Ensure that we handle C++11 in-class initializers properly as an extension. +// In this case, there is no user-declared default constructor, so we +// recursively apply the value-initialization checks, but we will emit a +// constructor call anyway, because the default constructor is not trivial. +struct V { + int n; + int &r = n; // expected-warning {{C++11}} +}; +V v = V(); // ok +struct W { + int n; + S s = { n }; // expected-warning {{C++11}} +}; +W w = W(); // ok + +// Ensure we're not faking this up by making the default constructor +// non-trivial. +#define static_assert(B, S) typedef int assert_failed[(B) ? 1 : -1]; +static_assert(__has_trivial_constructor(S), ""); +static_assert(__has_trivial_constructor(T), ""); +static_assert(__has_trivial_constructor(U), ""); +static_assert(!__has_trivial_constructor(V), ""); +static_assert(!__has_trivial_constructor(W), ""); diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp index 5467a92..e03c216 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s void nondecl(int (*f)(int x = 5)) // expected-error {{default arguments can only be specified}} { @@ -8,6 +8,9 @@ void nondecl(int (*f)(int x = 5)) // expected-error {{default arguments can only struct X0 { int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}} + void (*g())(int = 22); // expected-error{{default arguments can only be specified for parameters in a function declaration}} + void (*h(int = 49))(int); + auto i(int) -> void (*)(int = 9); // expected-error{{default arguments can only be specified for parameters in a function declaration}} void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}} }; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp index 9b5ef78..4227d82 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp @@ -38,8 +38,8 @@ namespace copy { }; struct NonConst { - NonConst(NonConst&) = default; // expected-error {{must be defaulted outside the class}} - NonConst& operator=(NonConst&) = default; // expected-error {{must be defaulted outside the class}} + NonConst(NonConst&) = default; + NonConst& operator=(NonConst&) = default; }; struct NonConst2 { diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp index 34a8c85..ec1ccbf 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp @@ -1,10 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s struct A { }; -A::A (enum { e1 }) {} // expected-error{{can not be defined in a parameter}} \ -// expected-error{{out-of-line definition}} -void A::f(enum { e2 }) {} // expected-error{{can not be defined in a parameter}} \ -// expected-error{{out-of-line definition}} +A::A (enum { e1 }) {} // expected-error{{can not be defined in a parameter}} +void A::f(enum { e2 }) {} // expected-error{{can not be defined in a parameter}} enum { e3 } A::g() { } // expected-error{{can not be defined in the result type}} \ // expected-error{{out-of-line definition}} diff --git a/test/CXX/except/except.spec/p14-ir.cpp b/test/CXX/except/except.spec/p14-ir.cpp index 81fbf7d..9b41f3d 100644 --- a/test/CXX/except/except.spec/p14-ir.cpp +++ b/test/CXX/except/except.spec/p14-ir.cpp @@ -27,12 +27,12 @@ struct X5 : X0, X4 { }; void test(X2 x2, X3 x3, X5 x5) { // CHECK: define linkonce_odr void @_ZN2X2C1ERKS_(%struct.X2* %this, %struct.X2*) unnamed_addr - // CHECK: call void @_ZN2X2C2ERKS_({{.*}}) nounwind + // CHECK: call void @_ZN2X2C2ERKS_({{.*}}) [[NUW:#[0-9]+]] // CHECK-NEXT: ret void // CHECK-NEXT: } X2 x2a(x2); // CHECK: define linkonce_odr void @_ZN2X3C1ERKS_(%struct.X3* %this, %struct.X3*) unnamed_addr - // CHECK: call void @_ZN2X3C2ERKS_({{.*}}) nounwind + // CHECK: call void @_ZN2X3C2ERKS_({{.*}}) [[NUW]] // CHECK-NEXT: ret void // CHECK-NEXT: } X3 x3a(x3); @@ -56,7 +56,7 @@ struct X9 : X6, X7 { }; void test() { // CHECK: define linkonce_odr void @_ZN2X8C1Ev(%struct.X8* %this) unnamed_addr - // CHECK: call void @_ZN2X8C2Ev({{.*}}) nounwind + // CHECK: call void @_ZN2X8C2Ev({{.*}}) [[NUW]] // CHECK-NEXT: ret void X8(); @@ -67,13 +67,15 @@ void test() { X9(); // CHECK: define linkonce_odr void @_ZN2X9C2Ev(%struct.X9* %this) unnamed_addr - // CHECK: call void @_ZN2X6C2Ev({{.*}}) nounwind + // CHECK: call void @_ZN2X6C2Ev({{.*}}) [[NUW]] // FIXME: and here: // CHECK-NEXT: bitcast // CHECK-NEXT: call void @_ZN2X7C2Ev({{.*}}) // CHECK: ret void // CHECK: define linkonce_odr void @_ZN2X8C2Ev(%struct.X8* %this) unnamed_addr - // CHECK: call void @_ZN2X6C2Ev({{.*}}) nounwind + // CHECK: call void @_ZN2X6C2Ev({{.*}}) [[NUW]] // CHECK-NEXT: ret void } + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CXX/except/except.spec/p14.cpp b/test/CXX/except/except.spec/p14.cpp index ff21ab8..99ed2fd 100644 --- a/test/CXX/except/except.spec/p14.cpp +++ b/test/CXX/except/except.spec/p14.cpp @@ -101,3 +101,14 @@ namespace PR14141 { ~Derived3() noexcept(true) = default; // expected-error {{does not match the calculated}} }; } + +namespace rdar13017229 { + struct Base { + virtual ~Base() {} + }; + + struct Derived : Base { + virtual ~Derived(); + Typo foo(); // expected-error{{unknown type name 'Typo'}} + }; +} diff --git a/test/CXX/except/except.spec/p9-noexcept.cpp b/test/CXX/except/except.spec/p9-noexcept.cpp index 7c8d0ef..3fd45c5 100644 --- a/test/CXX/except/except.spec/p9-noexcept.cpp +++ b/test/CXX/except/except.spec/p9-noexcept.cpp @@ -7,9 +7,10 @@ void target() noexcept // CHECK: invoke void @_Z8externalv() external(); } -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) // CHECK-NEXT: catch i8* null -// CHECK-NEXT: call void @_ZSt9terminatev() noreturn nounwind +// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 +// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]] // CHECK-NEXT: unreachable void reverse() noexcept(false) @@ -17,3 +18,5 @@ void reverse() noexcept(false) // CHECK: call void @_Z8externalv() external(); } + +// CHECK: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index 9e6716d..065a12b 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -594,3 +594,16 @@ static const bool or_value = and_or<true>::or_value; static_assert(and_value == false, ""); static_assert(or_value == true, ""); + +namespace rdar13090123 { + typedef __INTPTR_TYPE__ intptr_t; + + constexpr intptr_t f(intptr_t x) { + return (((x) >> 21) * 8); // expected-note{{subexpression not valid in a constant expression}} + } + + extern "C" int foo; + + constexpr intptr_t i = f((intptr_t)&foo - 10); // expected-error{{constexpr variable 'i' must be initialized by a constant expression}} \ + // expected-note{{in call to 'f((char*)&foo + -10)'}} +} diff --git a/test/CXX/expr/expr.post/expr.call/p7-0x.cpp b/test/CXX/expr/expr.post/expr.call/p7-0x.cpp index d51ba09..018609d 100644 --- a/test/CXX/expr/expr.post/expr.call/p7-0x.cpp +++ b/test/CXX/expr/expr.post/expr.call/p7-0x.cpp @@ -9,11 +9,22 @@ struct X2 { ~X2(); }; +struct X3 { + X3(const X3&) = default; +}; + +struct X4 { + X4(const X4&) = default; + X4(X4&); +}; + void vararg(...); -void f(X1 x1, X2 x2) { - vararg(x1); // okay +void f(X1 x1, X2 x2, X3 x3, X4 x4) { + vararg(x1); // OK vararg(x2); // expected-error{{cannot pass object of non-trivial type 'X2' through variadic function; call will abort at runtime}} + vararg(x3); // OK + vararg(x4); // expected-error{{cannot pass object of non-trivial type 'X4' through variadic function; call will abort at runtime}} } diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp index b84cec6..6657991 100644 --- a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp @@ -61,9 +61,26 @@ namespace PR10036 { } } +namespace PR15290 { + template<typename T> + class A { + T v_; + friend int add_to_v(A &t) noexcept(noexcept(v_ + 42)) + { + return t.v_ + 42; + } + }; + void f() + { + A<int> t; + add_to_v(t); + } +} + namespace Static { struct X1 { int m; + // FIXME: This should be accepted. static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}} static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}} @@ -99,3 +116,23 @@ namespace PR12564 { void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // expected-error {{cannot bind to a value of unrelated type}} }; } + +namespace rdar13473493 { + template <typename F> + class wrap + { + public: + template <typename... Args> + auto operator()(Args&&... args) const -> decltype(wrapped(args...)) // expected-note{{candidate template ignored: substitution failure [with Args = <int>]: use of undeclared identifier 'wrapped'}} + { + return wrapped(args...); + } + + private: + F wrapped; + }; + + void test(wrap<int (*)(int)> w) { + w(5); // expected-error{{no matching function for call to object of type 'wrap<int (*)(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 index 6fe3b25..8a6e792 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -13,7 +13,7 @@ void test_special_member_functions(MoveOnly mo, int i) { 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}} + lambda1 = lambda1; // expected-error{{copy assignment operator is implicitly deleted}} // Move assignment operator lambda1 = move(lambda1); diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp index 68460f0..9dffc1f 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -5,7 +5,8 @@ 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}} + // FIXME: GCC accepts the [[gnu::noreturn]] attribute here. + auto nrl2 = []() [[gnu::noreturn]] { return; }; // expected-warning{{attribute 'noreturn' ignored}} } template<typename T> diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp index 49b9c66..407b083 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp @@ -2,10 +2,11 @@ template<typename T> void test_attributes() { - auto nrl = []() [[noreturn]] {}; // expected-error{{lambda declared 'noreturn' should not return}} + // FIXME: GCC accepts [[gnu::noreturn]] here. + auto nrl = []() [[gnu::noreturn]] {}; // expected-warning{{attribute 'noreturn' ignored}} } -template void test_attributes<int>(); // expected-note{{in instantiation of function}} +template void test_attributes<int>(); template<typename T> void call_with_zero() { diff --git a/test/CXX/lex/lex.literal/lex.ext/p5.cpp b/test/CXX/lex/lex.literal/lex.ext/p5.cpp index 4655aa17..06c091d 100644 --- a/test/CXX/lex/lex.literal/lex.ext/p5.cpp +++ b/test/CXX/lex/lex.literal/lex.ext/p5.cpp @@ -11,3 +11,10 @@ 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 +double &i6 = u\ +8\ +R\ +"(foo)"\ +_\ +x\ +1; // ok diff --git a/test/CXX/lex/lex.pptoken/p3-0x.cpp b/test/CXX/lex/lex.pptoken/p3-0x.cpp index 3d56ac1..418a0f3 100644 --- a/test/CXX/lex/lex.pptoken/p3-0x.cpp +++ b/test/CXX/lex/lex.pptoken/p3-0x.cpp @@ -9,3 +9,7 @@ template void f<::b>(); #define x a<:: ## : b :> int d = x; // expected-error {{pasting formed ':::', an invalid preprocessing token}} expected-error {{expected unqualified-id}} + +const char xs[] = R"(\ +??=\U0000)"; +static_assert(sizeof(xs) == 12, "did not revert all changes"); diff --git a/test/CXX/over/over.oper/over.literal/p8.cpp b/test/CXX/over/over.oper/over.literal/p8.cpp index 6f63610..70a1843 100644 --- a/test/CXX/over/over.oper/over.literal/p8.cpp +++ b/test/CXX/over/over.oper/over.literal/p8.cpp @@ -7,8 +7,7 @@ namespace std { 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}} +template<char...> int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-warning {{reserved}} float operator ""E(const char *); // expected-error {{invalid suffix on literal}} 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}} diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp index 597e327..3337412 100644 --- a/test/CXX/special/class.copy/implicit-move.cpp +++ b/test/CXX/special/class.copy/implicit-move.cpp @@ -54,7 +54,7 @@ void test_basic_exclusion() { static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), ""); HasMoveConstructor hmc; - hmc = HasMoveConstructor(); // expected-error {{selected implicitly-deleted copy assignment}} + hmc = HasMoveConstructor(); // expected-error {{object of type 'HasMoveConstructor' cannot be assigned because its copy assignment operator is implicitly deleted}} (HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}} HasMoveAssignment hma; diff --git a/test/CXX/special/class.copy/p12-0x.cpp b/test/CXX/special/class.copy/p12-0x.cpp new file mode 100644 index 0000000..17b3191 --- /dev/null +++ b/test/CXX/special/class.copy/p12-0x.cpp @@ -0,0 +1,216 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// expected-no-diagnostics + +template<typename T, bool B> struct trivially_copyable_check { + static_assert(B == __has_trivial_copy(T), ""); + static_assert(B == __is_trivially_constructible(T, T), ""); + static_assert(B == __is_trivially_constructible(T, const T &), ""); + static_assert(B == __is_trivially_constructible(T, T &&), ""); + typedef void type; +}; +template<typename T> using trivially_copyable = + typename trivially_copyable_check<T, true>::type; +template<typename T> using not_trivially_copyable = + typename trivially_copyable_check<T, false>::type; + +struct Trivial {}; +using _ = trivially_copyable<Trivial>; + +// A copy/move constructor for class X is trivial if it is not user-provided, +struct UserProvided { + UserProvided(const UserProvided &); +}; +using _ = not_trivially_copyable<UserProvided>; + +// its declared parameter type is the same as if it had been implicitly +// declared, +struct NonConstCopy { + NonConstCopy(NonConstCopy &) = default; +}; +using _ = not_trivially_copyable<NonConstCopy>; + +// class X has no virtual functions +struct VFn { + virtual void f(); +}; +using _ = not_trivially_copyable<VFn>; + +// and no virtual base classes +struct VBase : virtual Trivial {}; +using _ = not_trivially_copyable<VBase>; + +// and the constructor selected to copy/move each [direct subobject] is trivial +struct TemplateCtor { + template<typename T> TemplateCtor(T &); +}; +using _ = trivially_copyable<TemplateCtor>; +struct TemplateCtorMember { + TemplateCtor tc; +}; +using _ = trivially_copyable<TemplateCtorMember>; + +// We can select a non-trivial copy ctor even if there is a trivial one. +struct MutableTemplateCtorMember { + mutable TemplateCtor mtc; +}; +static_assert(!__is_trivially_constructible(MutableTemplateCtorMember, const MutableTemplateCtorMember &), ""); +static_assert(__is_trivially_constructible(MutableTemplateCtorMember, MutableTemplateCtorMember &&), ""); +struct MutableTemplateCtorMember2 { + MutableTemplateCtorMember2(const MutableTemplateCtorMember2 &) = default; + MutableTemplateCtorMember2(MutableTemplateCtorMember2 &&) = default; + mutable TemplateCtor mtc; +}; +static_assert(!__is_trivially_constructible(MutableTemplateCtorMember2, const MutableTemplateCtorMember2 &), ""); +static_assert(__is_trivially_constructible(MutableTemplateCtorMember2, MutableTemplateCtorMember2 &&), ""); + +// Both trivial and non-trivial special members. +struct TNT { + TNT(const TNT &) = default; // trivial + TNT(TNT &); // non-trivial + + TNT(TNT &&) = default; // trivial + TNT(const TNT &&); // non-trivial +}; + +static_assert(!__has_trivial_copy(TNT), "lie deliberately for gcc compatibility"); +static_assert(__is_trivially_constructible(TNT, TNT), ""); +static_assert(!__is_trivially_constructible(TNT, TNT &), ""); +static_assert(__is_trivially_constructible(TNT, const TNT &), ""); +static_assert(!__is_trivially_constructible(TNT, volatile TNT &), ""); +static_assert(__is_trivially_constructible(TNT, TNT &&), ""); +static_assert(!__is_trivially_constructible(TNT, const TNT &&), ""); +static_assert(!__is_trivially_constructible(TNT, volatile TNT &&), ""); + +// This has only trivial special members. +struct DerivedFromTNT : TNT {}; + +static_assert(__has_trivial_copy(DerivedFromTNT), ""); +static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT), ""); +static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &), ""); +static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &), ""); +static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &), ""); +static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &&), ""); +static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &&), ""); +static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &&), ""); + +// This has only trivial special members. +struct TNTMember { + TNT tnt; +}; + +static_assert(__has_trivial_copy(TNTMember), ""); +static_assert(__is_trivially_constructible(TNTMember, TNTMember), ""); +static_assert(__is_trivially_constructible(TNTMember, TNTMember &), ""); +static_assert(__is_trivially_constructible(TNTMember, const TNTMember &), ""); +static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &), ""); +static_assert(__is_trivially_constructible(TNTMember, TNTMember &&), ""); +static_assert(__is_trivially_constructible(TNTMember, const TNTMember &&), ""); +static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &&), ""); + +struct NCCTNT : NonConstCopy, TNT {}; + +static_assert(!__has_trivial_copy(NCCTNT), ""); +static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT), ""); +static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &), ""); +static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &), ""); +static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &), ""); +static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &&), ""); +static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &&), ""); +static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &&), ""); + +struct TemplateCtorNoMove { + TemplateCtorNoMove(const TemplateCtorNoMove &) = default; + template<typename T> TemplateCtorNoMove(T &&); +}; +static_assert(__is_trivially_constructible(TemplateCtorNoMove, const TemplateCtorNoMove &), ""); +static_assert(!__is_trivially_constructible(TemplateCtorNoMove, TemplateCtorNoMove &&), ""); + +struct UseTemplateCtorNoMove { + TemplateCtorNoMove tcnm; +}; +static_assert(__is_trivially_constructible(UseTemplateCtorNoMove, const UseTemplateCtorNoMove &), ""); +static_assert(!__is_trivially_constructible(UseTemplateCtorNoMove, UseTemplateCtorNoMove &&), ""); + +struct TemplateCtorNoMoveSFINAE { + TemplateCtorNoMoveSFINAE(const TemplateCtorNoMoveSFINAE &) = default; + template<typename T, typename U = typename T::error> TemplateCtorNoMoveSFINAE(T &&); +}; +static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, const TemplateCtorNoMoveSFINAE &), ""); +static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, TemplateCtorNoMoveSFINAE &&), ""); + +struct UseTemplateCtorNoMoveSFINAE { + TemplateCtorNoMoveSFINAE tcnm; +}; +static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, const UseTemplateCtorNoMoveSFINAE &), ""); +static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, UseTemplateCtorNoMoveSFINAE &&), ""); + +namespace TrivialityDependsOnImplicitDeletion { + struct PrivateMove { + PrivateMove(const PrivateMove &) = default; + private: + PrivateMove(PrivateMove &&); + friend class Access; + }; + static_assert(__is_trivially_constructible(PrivateMove, const PrivateMove &), ""); + static_assert(!__is_trivially_constructible(PrivateMove, PrivateMove &&), ""); + + struct NoAccess { + PrivateMove pm; + // NoAccess's move would be deleted, so is suppressed, + // so moves of it use PrivateMove's copy ctor, which is trivial. + }; + static_assert(__is_trivially_constructible(NoAccess, const NoAccess &), ""); + static_assert(__is_trivially_constructible(NoAccess, NoAccess &&), ""); + struct TopNoAccess : NoAccess {}; + static_assert(__is_trivially_constructible(TopNoAccess, const TopNoAccess &), ""); + static_assert(__is_trivially_constructible(TopNoAccess, TopNoAccess &&), ""); + + struct Access { + PrivateMove pm; + // NoAccess's move would *not* be deleted, so is *not* suppressed, + // so moves of it use PrivateMove's move ctor, which is not trivial. + }; + static_assert(__is_trivially_constructible(Access, const Access &), ""); + static_assert(!__is_trivially_constructible(Access, Access &&), ""); + struct TopAccess : Access {}; + static_assert(__is_trivially_constructible(TopAccess, const TopAccess &), ""); + static_assert(!__is_trivially_constructible(TopAccess, TopAccess &&), ""); +} + +namespace TrivialityDependsOnDestructor { + class HasInaccessibleDestructor { ~HasInaccessibleDestructor() = default; }; + struct HasImplicitlyDeletedDestructor : HasInaccessibleDestructor {}; + struct HasImplicitlyDeletedCopyCtor : HasImplicitlyDeletedDestructor { + HasImplicitlyDeletedCopyCtor() = default; + template<typename T> HasImplicitlyDeletedCopyCtor(T &&); + // Copy ctor is deleted but trivial. + // Move ctor is suppressed. + HasImplicitlyDeletedCopyCtor(const HasImplicitlyDeletedCopyCtor&) = default; + HasImplicitlyDeletedCopyCtor(HasImplicitlyDeletedCopyCtor&&) = default; + }; + struct Test : HasImplicitlyDeletedCopyCtor { + Test(const Test&) = default; + Test(Test&&) = default; + }; + // Implicit copy ctor calls deleted trivial copy ctor. + static_assert(__has_trivial_copy(Test), ""); + // This is false because the destructor is deleted. + static_assert(!__is_trivially_constructible(Test, const Test &), ""); + // Implicit move ctor calls template ctor. + static_assert(!__is_trivially_constructible(Test, Test &&), ""); + + struct HasAccessibleDestructor { ~HasAccessibleDestructor() = default; }; + struct HasImplicitlyDefaultedDestructor : HasAccessibleDestructor {}; + struct HasImplicitlyDefaultedCopyCtor : HasImplicitlyDefaultedDestructor { + template<typename T> HasImplicitlyDefaultedCopyCtor(T &&); + // Copy ctor is trivial. + // Move ctor is trivial. + }; + struct Test2 : HasImplicitlyDefaultedCopyCtor {}; + // Implicit copy ctor calls trivial copy ctor. + static_assert(__has_trivial_copy(Test2), ""); + static_assert(__is_trivially_constructible(Test2, const Test2 &), ""); + // Implicit move ctor calls trivial move ctor. + static_assert(__is_trivially_constructible(Test2, Test2 &&), ""); +} diff --git a/test/CXX/special/class.copy/p18-cxx11.cpp b/test/CXX/special/class.copy/p18-cxx11.cpp new file mode 100644 index 0000000..7b09dd6 --- /dev/null +++ b/test/CXX/special/class.copy/p18-cxx11.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify +// expected-no-diagnostics + +// C++98 [class.copy]p10 / C++11 [class.copy]p18. + +// The implicitly-declared copy assignment operator for a class X will have the form +// X& X::operator=(const X&) +// if [every direct subobject] has a copy assignment operator whose first parameter is +// of type 'const volatile[opt] T &' or 'T'. Otherwise, it will have the form +// X &X::operator=(X&) + +struct ConstCopy { + ConstCopy &operator=(const ConstCopy &); +}; + +struct NonConstCopy { + NonConstCopy &operator=(NonConstCopy &); +}; + +struct DeletedConstCopy { + DeletedConstCopy &operator=(const DeletedConstCopy &) = delete; +}; + +struct DeletedNonConstCopy { + DeletedNonConstCopy &operator=(DeletedNonConstCopy &) = delete; +}; + +struct ImplicitlyDeletedConstCopy { + ImplicitlyDeletedConstCopy &operator=(ImplicitlyDeletedConstCopy &&); +}; + +struct ByValueCopy { + ByValueCopy &operator=(ByValueCopy); +}; + +struct AmbiguousConstCopy { + AmbiguousConstCopy &operator=(const AmbiguousConstCopy&); + AmbiguousConstCopy &operator=(AmbiguousConstCopy); +}; + + +struct A : ConstCopy {}; +struct B : NonConstCopy { ConstCopy a; }; +struct C : ConstCopy { NonConstCopy a; }; +struct D : DeletedConstCopy {}; +struct E : DeletedNonConstCopy {}; +struct F { ImplicitlyDeletedConstCopy a; }; +struct G : virtual B {}; +struct H : ByValueCopy {}; +struct I : AmbiguousConstCopy {}; + +struct Test { + friend A &A::operator=(const A &); + friend B &B::operator=(B &); + friend C &C::operator=(C &); + friend D &D::operator=(const D &); + friend E &E::operator=(E &); + friend F &F::operator=(const F &); + friend G &G::operator=(G &); + friend H &H::operator=(const H &); + friend I &I::operator=(const I &); +}; diff --git a/test/CXX/special/class.copy/p23-cxx11.cpp b/test/CXX/special/class.copy/p23-cxx11.cpp index 7c04a82..90945c5 100644 --- a/test/CXX/special/class.copy/p23-cxx11.cpp +++ b/test/CXX/special/class.copy/p23-cxx11.cpp @@ -143,6 +143,6 @@ namespace PR13381 { }; void g() { T t; - t = T(); // expected-error{{implicitly-deleted copy assignment}} + t = T(); // expected-error{{object of type 'PR13381::T' cannot be assigned because its copy assignment operator is implicitly deleted}} } } diff --git a/test/CXX/special/class.copy/p25-0x.cpp b/test/CXX/special/class.copy/p25-0x.cpp new file mode 100644 index 0000000..c7224ae --- /dev/null +++ b/test/CXX/special/class.copy/p25-0x.cpp @@ -0,0 +1,202 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// expected-no-diagnostics + +template<typename T, bool B> struct trivially_assignable_check { + static_assert(B == __has_trivial_assign(T), ""); + static_assert(B == __is_trivially_assignable(T&, T), ""); + static_assert(B == __is_trivially_assignable(T&, const T &), ""); + static_assert(B == __is_trivially_assignable(T&, T &&), ""); + static_assert(B == __is_trivially_assignable(T&&, T), ""); + static_assert(B == __is_trivially_assignable(T&&, const T &), ""); + static_assert(B == __is_trivially_assignable(T&&, T &&), ""); + typedef void type; +}; +template<typename T> using trivially_assignable = + typename trivially_assignable_check<T, true>::type; +template<typename T> using not_trivially_assignable = + typename trivially_assignable_check<T, false>::type; + +struct Trivial {}; +using _ = trivially_assignable<Trivial>; + +// A copy/move assignment operator for class X is trivial if it is not user-provided, +struct UserProvided { + UserProvided &operator=(const UserProvided &); +}; +using _ = not_trivially_assignable<UserProvided>; + +// its declared parameter type is the same as if it had been implicitly +// declared, +struct NonConstCopy { + NonConstCopy &operator=(NonConstCopy &) = default; +}; +using _ = not_trivially_assignable<NonConstCopy>; + +// class X has no virtual functions +struct VFn { + virtual void f(); +}; +using _ = not_trivially_assignable<VFn>; + +// and no virtual base classes +struct VBase : virtual Trivial {}; +using _ = not_trivially_assignable<VBase>; + +// and the assignment operator selected to copy/move each [direct subobject] is trivial +struct TemplateCtor { + template<typename T> TemplateCtor operator=(T &); +}; +using _ = trivially_assignable<TemplateCtor>; +struct TemplateCtorMember { + TemplateCtor tc; +}; +using _ = trivially_assignable<TemplateCtorMember>; +struct MutableTemplateCtorMember { + mutable TemplateCtor mtc; +}; +static_assert(!__is_trivially_assignable(MutableTemplateCtorMember, const MutableTemplateCtorMember &), ""); +static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTemplateCtorMember &&), ""); + +// Both trivial and non-trivial special members. +struct TNT { + TNT &operator=(const TNT &) = default; // trivial + TNT &operator=(TNT &); // non-trivial + + TNT &operator=(TNT &&) = default; // trivial + TNT &operator=(const TNT &&); // non-trivial +}; + +static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility"); +static_assert(__is_trivially_assignable(TNT, TNT), ""); +static_assert(!__is_trivially_assignable(TNT, TNT &), ""); +static_assert(__is_trivially_assignable(TNT, const TNT &), ""); +static_assert(!__is_trivially_assignable(TNT, volatile TNT &), ""); +static_assert(__is_trivially_assignable(TNT, TNT &&), ""); +static_assert(!__is_trivially_assignable(TNT, const TNT &&), ""); +static_assert(!__is_trivially_assignable(TNT, volatile TNT &&), ""); + +// This has only trivial special members. +struct DerivedFromTNT : TNT {}; + +static_assert(__has_trivial_assign(DerivedFromTNT), ""); +static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT), ""); +static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &), ""); +static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &), ""); +static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &), ""); +static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &&), ""); +static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &&), ""); +static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &&), ""); + +// This has only trivial special members. +struct TNTMember { + TNT tnt; +}; + +static_assert(__has_trivial_assign(TNTMember), ""); +static_assert(__is_trivially_assignable(TNTMember, TNTMember), ""); +static_assert(__is_trivially_assignable(TNTMember, TNTMember &), ""); +static_assert(__is_trivially_assignable(TNTMember, const TNTMember &), ""); +static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &), ""); +static_assert(__is_trivially_assignable(TNTMember, TNTMember &&), ""); +static_assert(__is_trivially_assignable(TNTMember, const TNTMember &&), ""); +static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &&), ""); + +struct NCCTNT : NonConstCopy, TNT {}; + +static_assert(!__has_trivial_assign(NCCTNT), ""); +static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT), ""); +static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &), ""); +static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &), ""); +static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &), ""); +static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &&), ""); +static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &&), ""); +static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &&), ""); + +struct MultipleTrivial { + // All four of these are trivial. + MultipleTrivial &operator=(const MultipleTrivial &) & = default; + MultipleTrivial &operator=(const MultipleTrivial &) && = default; + MultipleTrivial &operator=(MultipleTrivial &&) & = default; + MultipleTrivial &operator=(MultipleTrivial &&) && = default; +}; + +using _ = trivially_assignable<MultipleTrivial>; + +struct RefQualifier { + RefQualifier &operator=(const RefQualifier &) & = default; + RefQualifier &operator=(const RefQualifier &) &&; + RefQualifier &operator=(RefQualifier &&) &; + RefQualifier &operator=(RefQualifier &&) && = default; +}; +struct DerivedFromRefQualifier : RefQualifier { + // Both of these call the trivial copy operation. + DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) & = default; + DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) && = default; + // Both of these call the non-trivial move operation. + DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) & = default; + DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) && = default; +}; +static_assert(__is_trivially_assignable(DerivedFromRefQualifier&, const DerivedFromRefQualifier&), ""); +static_assert(__is_trivially_assignable(DerivedFromRefQualifier&&, const DerivedFromRefQualifier&), ""); +static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&, DerivedFromRefQualifier&&), ""); +static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&&, DerivedFromRefQualifier&&), ""); + +struct TemplateAssignNoMove { + TemplateAssignNoMove &operator=(const TemplateAssignNoMove &) = default; + template<typename T> TemplateAssignNoMove &operator=(T &&); +}; +static_assert(__is_trivially_assignable(TemplateAssignNoMove, const TemplateAssignNoMove &), ""); +static_assert(!__is_trivially_assignable(TemplateAssignNoMove, TemplateAssignNoMove &&), ""); + +struct UseTemplateAssignNoMove { + TemplateAssignNoMove tanm; +}; +static_assert(__is_trivially_assignable(UseTemplateAssignNoMove, const UseTemplateAssignNoMove &), ""); +static_assert(!__is_trivially_assignable(UseTemplateAssignNoMove, UseTemplateAssignNoMove &&), ""); + +struct TemplateAssignNoMoveSFINAE { + TemplateAssignNoMoveSFINAE &operator=(const TemplateAssignNoMoveSFINAE &) = default; + template<typename T, typename U = typename T::error> TemplateAssignNoMoveSFINAE &operator=(T &&); +}; +static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, const TemplateAssignNoMoveSFINAE &), ""); +static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, TemplateAssignNoMoveSFINAE &&), ""); + +struct UseTemplateAssignNoMoveSFINAE { + TemplateAssignNoMoveSFINAE tanm; +}; +static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, const UseTemplateAssignNoMoveSFINAE &), ""); +static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, UseTemplateAssignNoMoveSFINAE &&), ""); + +namespace TrivialityDependsOnImplicitDeletion { + struct PrivateMove { + PrivateMove &operator=(const PrivateMove &) = default; + private: + PrivateMove &operator=(PrivateMove &&); + friend class Access; + }; + static_assert(__is_trivially_assignable(PrivateMove, const PrivateMove &), ""); + static_assert(!__is_trivially_assignable(PrivateMove, PrivateMove &&), ""); + + struct NoAccess { + PrivateMove pm; + // NoAccess's move would be deleted, so is suppressed, + // so moves of it use PrivateMove's copy ctor, which is trivial. + }; + static_assert(__is_trivially_assignable(NoAccess, const NoAccess &), ""); + static_assert(__is_trivially_assignable(NoAccess, NoAccess &&), ""); + struct TopNoAccess : NoAccess {}; + static_assert(__is_trivially_assignable(TopNoAccess, const TopNoAccess &), ""); + static_assert(__is_trivially_assignable(TopNoAccess, TopNoAccess &&), ""); + + struct Access { + PrivateMove pm; + // NoAccess's move would *not* be deleted, so is *not* suppressed, + // so moves of it use PrivateMove's move ctor, which is not trivial. + }; + static_assert(__is_trivially_assignable(Access, const Access &), ""); + static_assert(!__is_trivially_assignable(Access, Access &&), ""); + struct TopAccess : Access {}; + static_assert(__is_trivially_assignable(TopAccess, const TopAccess &), ""); + static_assert(!__is_trivially_assignable(TopAccess, TopAccess &&), ""); +} diff --git a/test/CXX/special/class.copy/p28-cxx11.cpp b/test/CXX/special/class.copy/p28-cxx11.cpp new file mode 100644 index 0000000..dc501d9 --- /dev/null +++ b/test/CXX/special/class.copy/p28-cxx11.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++98 %s -fsyntax-only +// RUN: %clang_cc1 -std=c++11 %s -verify + +// In C++11, we must perform overload resolution to determine which function is +// called by a defaulted assignment operator, and the selected operator might +// not be a copy or move assignment (it might be a specialization of a templated +// 'operator=', for instance). +struct A { + A &operator=(const A &); + + template<typename T> + A &operator=(T &&) { return T::error; } // expected-error {{no member named 'error' in 'A'}} +}; + +struct B : A { + B &operator=(B &&); +}; + +B &B::operator=(B &&) = default; // expected-note {{here}} diff --git a/test/CXX/special/class.ctor/p1.cpp b/test/CXX/special/class.ctor/p1.cpp index 4d82184..e19dc86 100644 --- a/test/CXX/special/class.ctor/p1.cpp +++ b/test/CXX/special/class.ctor/p1.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics + struct X0 { struct type { }; @@ -41,3 +41,15 @@ template<typename T> X1<T>::X1() { } template<typename T> (X1<T>::X1)(double) { } template<typename T> X1<T> X1<T>::f1(int) { return 0; } template<typename T> X1<T> (X1<T>::f1)(type) { return 0; } + +class X2 { + X2::X2(); // expected-error {{extra qualification on member 'X2'}} +}; + +// We used to parse 'X3::X3' as a member function declaration. +// DR 1435 and DR 1310 made this invalid. +typedef int T1; +struct X3 { + X3::X3(T1()); // expected-error {{extra qualification on member 'X3'}} +}; + diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp index 1aaeef2..0f4add8 100644 --- a/test/CXX/special/class.ctor/p5-0x.cpp +++ b/test/CXX/special/class.ctor/p5-0x.cpp @@ -149,26 +149,41 @@ static_assert(__has_trivial_constructor(Trivial), "Trivial is nontrivial"); class NonTrivialDefCtor1 { NonTrivialDefCtor1(); }; static_assert(!__has_trivial_constructor(NonTrivialDefCtor1), "NonTrivialDefCtor1 is trivial"); +#define ASSERT_NONTRIVIAL_IMPL(Class, Bases, Body) \ + class Class Bases { Body }; \ + static_assert(!__has_trivial_constructor(Class), ""); +#define ASSERT_NONTRIVIAL(Class, Bases, Body) \ + ASSERT_NONTRIVIAL_IMPL(Class, Bases, Body) \ + ASSERT_NONTRIVIAL_IMPL(Def ## Class, Bases, Def ## Class() = default; Body) \ + ASSERT_NONTRIVIAL_IMPL(Del ## Class, Bases, Del ## Class() = delete; Body) + // - its class has no virtual functions (10.3) and no virtual base classes (10.1), and -class NonTrivialDefCtor2 { virtual void f(); }; -static_assert(!__has_trivial_constructor(NonTrivialDefCtor2), "NonTrivialDefCtor2 is trivial"); -class NonTrivialDefCtor3 : virtual Trivial {}; -static_assert(!__has_trivial_constructor(NonTrivialDefCtor3), "NonTrivialDefCtor3 is trivial"); +ASSERT_NONTRIVIAL(NonTrivialDefCtor2, , virtual void f();) +ASSERT_NONTRIVIAL(NonTrivialDefCtor3, : virtual Trivial, ) // - no non-static data member of its class has a brace-or-equal-initializer, and -class NonTrivialDefCtor4 { int m = 52; }; -static_assert(!__has_trivial_constructor(NonTrivialDefCtor4), "NonTrivialDefCtor4 is trivial"); +ASSERT_NONTRIVIAL(NonTrivialDefCtor4, , int m = 52;) // - all the direct base classes of its class have trivial default constructors, and -class NonTrivialDefCtor5 : NonTrivialDefCtor1 {}; -static_assert(!__has_trivial_constructor(NonTrivialDefCtor5), "NonTrivialDefCtor5 is trivial"); +ASSERT_NONTRIVIAL(NonTrivialDefCtor5, : NonTrivialDefCtor1, ) // - for all the non-static data members of its class that are of class type (or array thereof), each such class // has a trivial default constructor. -class NonTrivialDefCtor6 { NonTrivialDefCtor1 t; }; -static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor5 is trivial"); +ASSERT_NONTRIVIAL(NonTrivialDefCtor6, , NonTrivialDefCtor1 t;) + +// FIXME: No core issue number yet. +// - its parameter-declaration-clause is equivalent to that of an implicit declaration. +struct NonTrivialDefCtor7 { + NonTrivialDefCtor7(...) = delete; +}; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor7), ""); +struct NonTrivialDefCtor8 { + NonTrivialDefCtor8(int = 0) = delete; +}; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor8), ""); // Otherwise, the default constructor is non-trivial. + class Trivial2 { Trivial2() = delete; }; static_assert(__has_trivial_constructor(Trivial2), "Trivial2 is trivial"); @@ -180,3 +195,15 @@ 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"); + +namespace PR14558 { + // Ensure we determine whether an explicitly-defaulted or deleted special + // member is trivial before we return to parsing the containing class. + struct A { + struct B { B() = default; } b; + struct C { C() = delete; } c; + }; + + static_assert(__has_trivial_constructor(A), ""); + static_assert(__has_trivial_constructor(A::B), ""); +} diff --git a/test/CXX/special/class.dtor/p3-0x.cpp b/test/CXX/special/class.dtor/p3-0x.cpp index 291353a..dc76e00 100644 --- a/test/CXX/special/class.dtor/p3-0x.cpp +++ b/test/CXX/special/class.dtor/p3-0x.cpp @@ -164,14 +164,16 @@ void tsw() { Sw<int> swi; Sw<B> swb; } -// CHECK-NOT: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} nounwind +// CHECK-NOT: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} # // CHECK: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} // CHECK: _ZTIi // CHECK: __cxa_call_unexpected -// CHECK: define linkonce_odr {{.*}} @_ZN2SwIiED1Ev({{.*}} nounwind +// CHECK: define linkonce_odr {{.*}} @_ZN2SwIiED1Ev({{.*}} [[ATTRGRP:#[0-9]+]] template <typename T> struct TVC : VX { virtual ~TVC(); }; template <typename T> TVC<T>::~TVC() {} + +// CHECK: attributes [[ATTRGRP]] = { nounwind{{.*}} } diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp index 0d073ce..e32279e 100644 --- a/test/CXX/special/class.dtor/p5-0x.cpp +++ b/test/CXX/special/class.dtor/p5-0x.cpp @@ -88,9 +88,10 @@ struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted f class D1 { void operator delete(void*); public: - virtual ~D1() = default; + virtual ~D1() = default; // expected-note {{here}} } d1; // ok -struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} +struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} \ + // expected-error {{deleted function '~D2' cannot override a non-deleted}} // implicitly-virtual destructor } d2; // expected-error {{deleted function}} struct D3 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} diff --git a/test/CXX/special/class.inhctor/elsewhere.cpp b/test/CXX/special/class.inhctor/elsewhere.cpp index 09fd3d5..184e902 100644 --- a/test/CXX/special/class.inhctor/elsewhere.cpp +++ b/test/CXX/special/class.inhctor/elsewhere.cpp @@ -9,49 +9,49 @@ struct B1 { B1(int); }; -using B1::B1; // expected-error {{using declaration can not refer to class member}} expected-error {{not supported}} +using B1::B1; // expected-error {{using declaration can not refer to class member}} -// C++0x [namespace.udecl]p10: +// C++11 [namespace.udecl]p10: // A using-declaration is a declaration and can therefore be used repeatedly // where (and only where) multiple declarations are allowed. struct I1 : B1 { - using B1::B1; // expected-note {{previous using declaration}} expected-error {{not supported}} - using B1::B1; // expected-error {{redeclaration of using decl}} expected-error {{not supported}} + using B1::B1; // expected-note {{previous using declaration}} + using B1::B1; // expected-error {{redeclaration of using decl}} }; -// C++0x [namespace.udecl]p3: +// C++11 [namespace.udecl]p3: // In a using declaration used as a member-declaration, the nested-name- // specifier shall name a base class of the class being defined. // If such a using-declaration names a constructor, the nested-name-specifier // shall name a direct base class of the class being defined. struct D1 : I1 { - using B1::B1; // expected-error {{'B1' is not a direct base of 'D1', can not inherit constructors}} expected-error {{not supported}} + 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>'}} expected-error {{not supported}} + 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>'}} expected-error {{not supported}} + 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}} expected-error {{not supported}} + 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>'}} expected-error {{not supported}} + 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/p1.cpp b/test/CXX/special/class.inhctor/p1.cpp new file mode 100644 index 0000000..57e9150 --- /dev/null +++ b/test/CXX/special/class.inhctor/p1.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s +// Per a core issue (no number yet), an ellipsis is always dropped. +struct A { + A(...); // expected-note {{here}} + A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 5{{here}} + A(int = 0, int = 0, ...); // expected-note {{here}} +}; + +struct B : A { // expected-note 3{{candidate}} + using A::A; // expected-warning 3{{inheriting constructor does not inherit ellipsis}} expected-note 4{{candidate}} expected-note 2{{deleted}} +}; + +B b0{}; +// expected-error@-1 {{call to implicitly-deleted default constructor}} +// expected-note@9 {{default constructor of 'B' is implicitly deleted because base class 'A' has multiple default constructors}} + +B b1{1}; +// FIXME: explain why the inheriting constructor was deleted +// expected-error@-2 {{call to implicitly-deleted function of 'B'}} + +B b2{1,2}; +// expected-error@-1 {{call to implicitly-deleted function of 'B'}} + +B b3{1,2,3}; +// ok + +B b4{1,2,3,4}; +// ok + +B b5{1,2,3,4,5}; +// expected-error@-1 {{no matching constructor for initialization of 'B'}} diff --git a/test/CXX/special/class.inhctor/p2.cpp b/test/CXX/special/class.inhctor/p2.cpp new file mode 100644 index 0000000..e426738 --- /dev/null +++ b/test/CXX/special/class.inhctor/p2.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<int> struct X {}; + +// Constructor characteristics are: +// - the template parameter list [FIXME] +// - the parameter-type-list +// - absence or presence of explicit +// - absence or presence of constexpr +struct A { + A(X<0>) {} // expected-note 2{{here}} + constexpr A(X<1>) {} + explicit A(X<2>) {} // expected-note 3{{here}} + explicit constexpr A(X<3>) {} // expected-note 2{{here}} +}; + +A a0 { X<0>{} }; +A a0i = { X<0>{} }; +constexpr A a0c { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}} +constexpr A a0ic = { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}} + +A a1 { X<1>{} }; +A a1i = { X<1>{} }; +constexpr A a1c { X<1>{} }; +constexpr A a1ic = { X<1>{} }; + +A a2 { X<2>{} }; +A a2i = { X<2>{} }; // expected-error {{constructor is explicit}} +constexpr A a2c { X<2>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}} +constexpr A a2ic = { X<2>{} }; // expected-error {{constructor is explicit}} + +A a3 { X<3>{} }; +A a3i = { X<3>{} }; // expected-error {{constructor is explicit}} +constexpr A a3c { X<3>{} }; +constexpr A a3ic = { X<3>{} }; // expected-error {{constructor is explicit}} + + +struct B : A { + using A::A; // expected-note 7{{here}} +}; + +B b0 { X<0>{} }; +B b0i = { X<0>{} }; +constexpr B b0c { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}} +constexpr B b0ic = { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}} + +B b1 { X<1>{} }; +B b1i = { X<1>{} }; +constexpr B b1c { X<1>{} }; +constexpr B b1ic = { X<1>{} }; + +B b2 { X<2>{} }; +B b2i = { X<2>{} }; // expected-error {{constructor is explicit}} +constexpr B b2c { X<2>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}} +constexpr B b2ic = { X<2>{} }; // expected-error {{constructor is explicit}} + +B b3 { X<3>{} }; +B b3i = { X<3>{} }; // expected-error {{constructor is explicit}} +constexpr B b3c { X<3>{} }; +constexpr B b3ic = { X<3>{} }; // expected-error {{constructor is explicit}} + + +// 'constexpr' is OK even if the constructor doesn't obey the constraints. +struct NonLiteral { NonLiteral(); }; +struct NonConstexpr { NonConstexpr(); constexpr NonConstexpr(int); }; // expected-note {{here}} +struct Constexpr { constexpr Constexpr(int) {} }; + +struct BothNonLiteral : NonLiteral, Constexpr { using Constexpr::Constexpr; }; // expected-note {{base class 'NonLiteral' of non-literal type}} +constexpr BothNonLiteral bothNL{42}; // expected-error {{constexpr variable cannot have non-literal type 'const BothNonLiteral'}} + +struct BothNonConstexpr : NonConstexpr, Constexpr { using Constexpr::Constexpr; }; // expected-note {{non-constexpr constructor 'NonConstexpr}} +constexpr BothNonConstexpr bothNC{42}; // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'BothNonConstexpr(42)'}} + + +struct ConstexprEval { + constexpr ConstexprEval(int a, const char *p) : k(p[a]) {} + char k; +}; +struct ConstexprEval2 { + char k2 = 'x'; +}; +struct ConstexprEval3 : ConstexprEval, ConstexprEval2 { + using ConstexprEval::ConstexprEval; +}; +constexpr ConstexprEval3 ce{4, "foobar"}; +static_assert(ce.k == 'a', ""); +static_assert(ce.k2 == 'x', ""); diff --git a/test/CXX/special/class.inhctor/p3.cpp b/test/CXX/special/class.inhctor/p3.cpp index d7093fb..f71ab16 100644 --- a/test/CXX/special/class.inhctor/p3.cpp +++ b/test/CXX/special/class.inhctor/p3.cpp @@ -5,7 +5,7 @@ struct B1 { B1(int, int); }; struct D1 : B1 { - using B1::B1; // expected-error {{not supported}} + using B1::B1; }; D1 d1a(1), d1b(1, 1); @@ -15,7 +15,7 @@ struct B2 { explicit B2(int, int = 0, int = 0); }; struct D2 : B2 { // expected-note 2 {{candidate constructor}} - using B2::B2; // expected-error {{not supported}} + using B2::B2; }; D2 d2a(1), d2b(1, 1), d2c(1, 1, 1); @@ -25,18 +25,18 @@ struct B3 { B3(void*); // expected-note {{inherited from here}} }; struct D3 : B3 { // expected-note 2 {{candidate constructor}} - using B3::B3; // expected-note {{candidate constructor (inherited)}} expected-error {{not supported}} + 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; // expected-error {{not supported}} + using B1::B1; }; template<typename T> struct T2 : T1<T> { - using T1<int>::T1; // expected-error {{not supported}} + using T1<int>::T1; }; template<typename T> struct T3 : T1<int> { - using T1<T>::T1; // expected-error {{not supported}} + using T1<T>::T1; }; struct U { friend T1<int>::T1(int); diff --git a/test/CXX/special/class.inhctor/p4.cpp b/test/CXX/special/class.inhctor/p4.cpp new file mode 100644 index 0000000..eea3bf2 --- /dev/null +++ b/test/CXX/special/class.inhctor/p4.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<int> struct X {}; + +// A[n inheriting] constructor [...] has the same access as the corresponding +// constructor [in the base class]. +struct A { +public: + A(X<0>) {} +protected: + A(X<1>) {} +private: + A(X<2>) {} // expected-note {{declared private here}} + friend class FA; +}; + +struct B : A { + using A::A; // expected-error {{private constructor}} expected-note {{implicitly declared protected here}} + friend class FB; +}; + +B b0{X<0>{}}; +B b1{X<1>{}}; // expected-error {{calling a protected constructor}} +B b2{X<2>{}}; // expected-note {{first required here}} + +struct C : B { + C(X<0> x) : B(x) {} + C(X<1> x) : B(x) {} +}; + +struct FB { + B b0{X<0>{}}; + B b1{X<1>{}}; +}; + +struct FA : A { + using A::A; // expected-note 2{{here}} +}; +FA fa0{X<0>{}}; +FA fa1{X<1>{}}; // expected-error {{calling a protected constructor}} +FA fa2{X<2>{}}; // expected-error {{calling a private constructor}} + + +// It is deleted if the corresponding constructor [...] is deleted. +struct G { + G(int) = delete; +}; +struct H : G { + using G::G; // expected-note {{marked deleted here}} +}; +H h(5); // expected-error {{call to implicitly-deleted function of 'H'}} + + +// Core defect: It is also deleted if multiple base constructors generate the +// same signature. +namespace DRnnnn { + struct A { + constexpr A(int, float = 0) {} + explicit A(int, int = 0) {} + + A(int, int, int = 0) = delete; + }; + struct B : A { + // FIXME: produce notes indicating why it was deleted + using A::A; // expected-note {{here}} + }; + + constexpr B b0(0, 0.0f); // ok, constexpr + B b1(0, 1); // expected-error {{call to implicitly-deleted}} +} diff --git a/test/CXX/special/class.inhctor/p7.cpp b/test/CXX/special/class.inhctor/p7.cpp index bfaa3ac..9ae160f 100644 --- a/test/CXX/special/class.inhctor/p7.cpp +++ b/test/CXX/special/class.inhctor/p7.cpp @@ -8,12 +8,12 @@ struct B2 { B2(int); // expected-note {{conflicting constructor}} }; struct D1 : B1, B2 { - using B1::B1; // expected-note {{inherited here}} expected-error {{not supported}} - using B2::B2; // expected-error {{already inherited constructor with the same signature}} expected-error {{not supported}} + using B1::B1; // expected-note {{inherited here}} + using B2::B2; // expected-error {{already inherited constructor with the same signature}} }; struct D2 : B1, B2 { - using B1::B1; // expected-error {{not supported}} - using B2::B2; // expected-error {{not supported}} + using B1::B1; + using B2::B2; D2(int); }; @@ -22,8 +22,8 @@ template<typename T> struct B3 { }; template<typename T> struct B4 : B3<T>, B1 { B4(); - using B3<T>::B3; // expected-note {{inherited here}} expected-error {{not supported}} - using B1::B1; // expected-error {{already inherited}} expected-error {{not supported}} + 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.inhctor/p8.cpp b/test/CXX/special/class.inhctor/p8.cpp new file mode 100644 index 0000000..e2b07df --- /dev/null +++ b/test/CXX/special/class.inhctor/p8.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// expected-no-diagnostics +struct A { + constexpr A(const int&) : rval(false) {} + constexpr A(const int&&) : rval(true) {} + bool rval; +}; +struct B : A { + using A::A; +}; + +constexpr int k = 0; +constexpr A a0{0}; +constexpr A a1{k}; +constexpr B b0{0}; +// This performs static_cast<(const int&)&&>(k), so calls the A(const int&) +// constructor. +constexpr B b1{k}; + +static_assert(a0.rval && !a1.rval && b0.rval && !b1.rval, ""); diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp index 726e222..9453798 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -351,6 +351,15 @@ void test_unexpanded_exprs(Types ...values) { // FIXME: Objective-C expressions will need to go elsewhere for (auto t : values) { } // expected-error{{expression contains unexpanded parameter pack 'values'}} + + switch (values) { } // expected-error{{expression contains unexpanded parameter pack 'values'}} + + do { } while (values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + +test: + goto *values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + void f(int arg = values); // expected-error{{default argument contains unexpanded parameter pack 'values'}} } // Test unexpanded parameter packs in partial specializations. diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.mm b/test/CXX/temp/temp.decls/temp.variadic/p5.mm new file mode 100644 index 0000000..d059826 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/p5.mm @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fobjc-exceptions -fexceptions -std=c++11 -fblocks -fsyntax-only -verify %s + +template<typename...Types> +void f(Types ...values) { + for (id x in values) { } // expected-error {{expression contains unexpanded parameter pack 'values'}} + @synchronized(values) { // expected-error {{expression contains unexpanded parameter pack 'values'}} + @throw values; // expected-error {{expression contains unexpanded parameter pack 'values'}} + } +} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp index 36b0700..dcf5a08 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp @@ -26,3 +26,24 @@ namespace ParameterPacksWithFunctions { unsigned_c<2> uc2 = f<float, double>(); } } + +namespace rdar12176336 { + typedef void (*vararg_func)(...); + + struct method { + vararg_func implementation; + + method(vararg_func implementation) : implementation(implementation) {} + + template<typename TReturnType, typename... TArguments, typename TFunctionType = TReturnType (*)(TArguments...)> + auto getImplementation() const -> TFunctionType + { + return reinterpret_cast<TFunctionType>(implementation); + } + }; + + void f() { + method m(nullptr); + auto imp = m.getImplementation<int, int, int>(); + } +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp index 90d2949..33efac0 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -15,8 +15,7 @@ void test_f1(int *ip, float fv) { f1(ip, fv); } -// TODO: this diagnostic can and should improve -template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: failed template argument deduction}} \ +template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: could not match 'T *' against 'ConvToIntPtr'}} \ // expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'float')}} struct ConvToIntPtr { @@ -28,3 +27,21 @@ void test_f2(int *ip, float *fp) { f2(ip, ip); // okay f2(ip, fp); // expected-error{{no matching function}} } + +namespace test3 { + template<typename T> + struct bar { }; + + template<typename T> + struct foo { + operator bar<T>(); + }; + + template<typename T> + void func(bar<T>) { // expected-note {{candidate template ignored: could not match 'bar' against 'foo'}} + } + + void test() { + func(foo<int>()); // expected-error {{no matching function}} + } +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp index 8b192fa..cd1d9f1 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -53,8 +53,9 @@ void test_simple_ref_deduction(int *ip, float *fp, double *dp) { } +// FIXME: Use the template parameter names in this diagnostic. template<typename ...Args1, typename ...Args2> -typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: failed template argument deduction}} +typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<type-parameter-0-0, type-parameter-0-1>' against 'int'}} template<typename ...Args1, typename ...Args2> typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...); diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp index 7774b5c..d7989e3 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -53,3 +53,16 @@ namespace DeduceNonTypeTemplateArgsInArray { tuple<unsigned_c<1>, unsigned_c<2>, unsigned_c<3>> >::value? 1 : -1]; } + +namespace DeduceWithDefaultArgs { + template<template<typename...> class Container> void f(Container<int>); // expected-note {{substitution failure [with Container = X]}} + template<typename, typename = int> struct X {}; + void g() { + // OK, use default argument for the second template parameter. + f(X<int>{}); + f(X<int, int>{}); + + // Not OK. + f(X<int, double>{}); // expected-error {{no matching function for call to 'f'}} + } +} diff --git a/test/CXX/temp/temp.res/temp.dep/p3.cpp b/test/CXX/temp/temp.res/temp.dep/p3.cpp index 88b4752..583fb4b 100644 --- a/test/CXX/temp/temp.res/temp.dep/p3.cpp +++ b/test/CXX/temp/temp.res/temp.dep/p3.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics struct A0 { struct K { }; }; @@ -42,3 +41,49 @@ namespace E2 { Y<A> ya; } + +namespace PR14402 { + template<typename T> + struct A { + typedef int n; + int f(); + + struct B {}; + struct C : B { + // OK, can't be sure whether we derive from A yet. + using A::n; + int g() { return f(); } + }; + + struct D { + using A::n; // expected-error {{using declaration refers into 'A<T>::', which is not a base class of 'D'}} + int g() { return f(); } // expected-error {{call to non-static member function 'f' of 'A' from nested type 'D'}} + }; + + struct E { char &f(); }; + struct F : E { + // FIXME: Reject this prior to instantiation; f() is known to return int. + char &g() { return f(); } + // expected-error@-1 {{'PR14402::A<int>::f' is not a member of class 'PR14402::A<int>::F'}} + // expected-error@-2 {{non-const lvalue reference to type 'char' cannot bind to a temporary of type 'int'}} + }; + }; + + template<> struct A<int>::B : A<int> {}; + A<int>::C::n n = A<int>::C().g(); + + // 'not a member' + char &r = A<int>::F().g(); // expected-note {{in instantiation of}} + template<> struct A<char>::E : A<char> {}; + // 'cannot bind to a temporary' + char &s = A<char>::F().g(); // expected-note {{in instantiation of}} + + struct X; + struct X { void f(); }; + struct X; + template<typename T> struct Y : X { + void g() { + X::f(); + } + }; +} 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 b0a19fb..75b198e 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 @@ -300,3 +300,8 @@ template<> template<typename T> void has_inline_namespaces::X0<X4>::mem_func_template(T&) { } template<> int has_inline_namespaces::X0<X4>::value = 13; + +namespace PR12938 { + template<typename> [[noreturn]] void func(); + template<> void func<int>(); +} 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 80f0598..e0c7b35 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp @@ -12,7 +12,7 @@ struct Y { constexpr int f() { return 0; } }; -template constexpr int Y<int>::f(); // expected-error{{explicit instantiation cannot be 'constexpr'}} +template constexpr int Y<int>::f() const; // expected-error{{explicit instantiation cannot be 'constexpr'}} template<typename T> struct Z { |