diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-12-22 02:22:31 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-12-22 02:22:31 +0000 |
| commit | cc36f698afe0132a3c7f5417d4469aee2f8cbaf2 (patch) | |
| tree | 206d9c5495d01c1a49678847a07ab27d34c44680 /clang/test | |
| parent | 1c3b1efa58a0365a4e0a2a77c4e1baf1b4ce7466 (diff) | |
| download | bcm5719-llvm-cc36f698afe0132a3c7f5417d4469aee2f8cbaf2.tar.gz bcm5719-llvm-cc36f698afe0132a3c7f5417d4469aee2f8cbaf2.zip | |
PR11614: Mark defaulted special constructors as constexpr if their implicit
definition would satisfy the constexpr requirements.
llvm-svn: 147128
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 9 | ||||
| -rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp | 55 | ||||
| -rw-r--r-- | clang/test/CXX/special/class.copy/p13-0x.cpp | 55 | ||||
| -rw-r--r-- | clang/test/CXX/special/class.ctor/p6-0x.cpp | 49 | ||||
| -rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx11.cpp | 9 | ||||
| -rw-r--r-- | clang/test/SemaCXX/enum-bitfield.cpp | 4 |
7 files changed, 170 insertions, 13 deletions
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 809a0cb1763..f173748e967 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -42,13 +42,12 @@ class C2 {} constexpr; // expected-error {{class cannot be marked constexpr}} struct S2 {} constexpr; // expected-error {{struct cannot be marked constexpr}} union U2 {} constexpr; // expected-error {{union cannot be marked constexpr}} enum E2 {} constexpr; // expected-error {{enum cannot be marked constexpr}} -// FIXME: Mark default constructors as 'constexpr' when appropriate. -constexpr class C3 {} c3 = C3(); // unexpected-error {{must be initialized by a constant expression}} unexpected-note {{non-constexpr constructor}} unexpected-note {{here}} -constexpr struct S3 {} s3 = S3(); // unexpected-error {{must be initialized by a constant expression}} unexpected-note {{non-constexpr constructor}} unexpected-note {{here}} +constexpr class C3 {} c3 = C3(); +constexpr struct S3 {} s3 = S3(); constexpr union U3 {} u3 = {}; constexpr enum E3 { V3 } e3 = V3; -class C4 {} constexpr c4 = C4(); // unexpected-error {{must be initialized by a constant expression}} unexpected-note {{non-constexpr constructor}} unexpected-note {{here}} -struct S4 {} constexpr s4 = S4(); // unexpected-error {{must be initialized by a constant expression}} unexpected-note {{non-constexpr constructor}} unexpected-note {{here}} +class C4 {} constexpr c4 = C4(); +struct S4 {} constexpr s4 = S4(); union U4 {} constexpr u4 = {}; enum E4 { V4 } constexpr e4 = V4; constexpr int; // expected-error {{constexpr can only be used in variable and function declarations}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 03406dbf918..1b31d21f36d 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -30,7 +30,7 @@ struct SS : S { // The definition of a constexpr function shall satisfy the following // constraints: -struct T : SS { // expected-note {{base class 'SS' of non-literal type}} +struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}} constexpr T(); // expected-error {{non-literal type 'T' cannot have constexpr members}} // - it shall not be virtual; diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp new file mode 100644 index 00000000000..d401a97ca25 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// An explicitly-defaulted function may be declared constexpr only if it would +// have been implicitly declared as constexpr. +struct S1 { + constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}} + constexpr S1(const S1&) = default; + constexpr S1(S1&&) = default; + constexpr S1 &operator=(const S1&) = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}} + constexpr S1 &operator=(S1&&) = default; // expected-error {{explicitly-defaulted move assignment operator may not have}} + constexpr ~S1() = default; // expected-error {{destructor cannot be marked constexpr}} + int n; +}; +struct NoCopyMove { + constexpr NoCopyMove() {} + NoCopyMove(const NoCopyMove&); + NoCopyMove(NoCopyMove&&); +}; +struct S2 { + constexpr S2() = default; + constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}} + constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}} + NoCopyMove ncm; +}; + +// If a function is explicitly defaulted on its first declaration +// -- it is implicitly considered to be constexpr if the implicit declaration +// would be +struct S3 { + S3() = default; // expected-note {{here}} + S3(const S3&) = default; + S3(S3&&) = default; + constexpr S3(int n) : n(n) {} + int n; +}; +constexpr S3 s3a = S3(0); +constexpr S3 s3b = s3a; +constexpr S3 s3c = S3(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct S4 { + S4() = default; + S4(const S4&) = default; // expected-note {{here}} + S4(S4&&) = default; // expected-note {{here}} + NoCopyMove ncm; +}; +constexpr S4 s4a; // ok +constexpr S4 s4b = S4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} +constexpr S4 s4c = s4a; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct S5 { + constexpr S5(); + int n = 1, m = n + 3; +}; +constexpr S5::S5() = default; +static_assert(S5().m == 4, ""); diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp new file mode 100644 index 00000000000..30d8c6ebad8 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p13-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If the implicitly-defined constructor would satisfy the requirements of a +// constexpr constructor, the implicitly-defined constructor is constexpr. +struct Constexpr1 { + constexpr Constexpr1() : n(0) {} + int n; +}; +constexpr Constexpr1 c1a = Constexpr1(Constexpr1()); // ok +constexpr Constexpr1 c1b = Constexpr1(Constexpr1(c1a)); // ok + +struct Constexpr2 { + Constexpr1 ce1; + constexpr Constexpr2() = default; + constexpr Constexpr2(const Constexpr2 &o) : ce1(o.ce1) {} + // no move constructor +}; + +constexpr Constexpr2 c2a = Constexpr2(Constexpr2()); // ok +constexpr Constexpr2 c2b = Constexpr2(Constexpr2(c2a)); // ok + +struct Constexpr3 { + Constexpr2 ce2; + // all special constructors are constexpr, move ctor calls ce2's copy ctor +}; + +constexpr Constexpr3 c3a = Constexpr3(Constexpr3()); // ok +constexpr Constexpr3 c3b = Constexpr3(Constexpr3(c3a)); // ok + +struct NonConstexprCopy { + constexpr NonConstexprCopy() = default; + NonConstexprCopy(const NonConstexprCopy &); + constexpr NonConstexprCopy(NonConstexprCopy &&) = default; + + int n = 42; +}; + +NonConstexprCopy::NonConstexprCopy(const NonConstexprCopy &) = default; // expected-note {{here}} + +constexpr NonConstexprCopy ncc1 = NonConstexprCopy(NonConstexprCopy()); // ok +constexpr NonConstexprCopy ncc2 = ncc1; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct NonConstexprDefault { + NonConstexprDefault() = default; + constexpr NonConstexprDefault(int n) : n(n) {} + int n; +}; +struct Constexpr4 { + NonConstexprDefault ncd; +}; + +constexpr NonConstexprDefault ncd = NonConstexprDefault(NonConstexprDefault(1)); +constexpr Constexpr4 c4a = { ncd }; +constexpr Constexpr4 c4b = Constexpr4(c4a); +constexpr Constexpr4 c4c = Constexpr4(static_cast<Constexpr4&&>(const_cast<Constexpr4&>(c4b))); diff --git a/clang/test/CXX/special/class.ctor/p6-0x.cpp b/clang/test/CXX/special/class.ctor/p6-0x.cpp new file mode 100644 index 00000000000..19e324d8df6 --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p6-0x.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +// Implicitly-defined default constructors are constexpr if the implicit +// definition would be. +struct NonConstexpr1 { // expected-note {{here}} + int a; +}; +struct NonConstexpr2 { // expected-note {{here}} + NonConstexpr1 nl; +}; +constexpr NonConstexpr1 nc1 = NonConstexpr1(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr1'}} +constexpr NonConstexpr2 nc2 = NonConstexpr2(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr2'}} + +struct Constexpr1 {}; +constexpr Constexpr1 c1 = Constexpr1(); // ok +struct NonConstexpr3 : virtual Constexpr1 {}; +constexpr NonConstexpr3 nc3 = NonConstexpr3(); // expected-error {{constant expression}} expected-note {{non-literal type 'const NonConstexpr3'}} + +struct Constexpr2 { + int a = 0; +}; +constexpr Constexpr2 c2 = Constexpr2(); // ok + +int n; +struct Member { + Member() : a(n) {} + constexpr Member(int&a) : a(a) {} + int &a; +}; +struct NonConstexpr4 { // expected-note {{here}} + Member m; +}; +constexpr NonConstexpr4 nc4 = NonConstexpr4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4'}} +struct Constexpr3 { + constexpr Constexpr3() : m(n) {} + Member m; +}; +constexpr Constexpr3 c3 = Constexpr3(); // ok +struct Constexpr4 { + Constexpr3 m; +}; +constexpr Constexpr4 c4 = Constexpr4(); // ok + + +// This rule breaks some legal C++98 programs! +struct A {}; // expected-note {{here}} +struct B { + friend A::A(); // expected-error {{non-constexpr declaration of 'A' follows constexpr declaration}} +}; diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 995cd2ffece..0993a982d8e 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -86,7 +86,7 @@ namespace TemplateArgumentConversion { using IntParam0 = IntParam<0>; using IntParam0 = IntParam<id(0)>; - using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} expected-error {{not an integral constant expression}} + using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} } namespace CaseStatements { @@ -517,16 +517,15 @@ struct D { }; static_assert(D().c.n == 42, ""); -struct E { // expected-note {{here}} +struct E { constexpr E() : p(&p) {} // expected-note {{pointer to temporary cannot be used to initialize a member in a constant expression}} void *p; }; constexpr const E &e1 = E(); // expected-error {{constant expression}} expected-note {{in call to 'E()'}} expected-note {{temporary created here}} // This is a constant expression if we elide the copy constructor call, and // is not a constant expression if we don't! But we do, so it is. -// FIXME: The move constructor is not currently implicitly defined as constexpr. -constexpr E e2 = E(); // unexpected-error {{constant expression}} unexpected-note {{here}} unexpected-note {{non-constexpr constructor 'E' cannot be used in a constant expression}} -static_assert(e2.p == &e2.p, ""); // unexpected-error {{constant expression}} unexpected-note {{initializer of 'e2' is not a constant expression}} +constexpr E e2 = E(); +static_assert(e2.p == &e2.p, ""); constexpr E e3; static_assert(e3.p == &e3.p, ""); diff --git a/clang/test/SemaCXX/enum-bitfield.cpp b/clang/test/SemaCXX/enum-bitfield.cpp index 8cfc21f9655..1a657408f8a 100644 --- a/clang/test/SemaCXX/enum-bitfield.cpp +++ b/clang/test/SemaCXX/enum-bitfield.cpp @@ -2,7 +2,7 @@ enum E {}; -struct Z {}; // expected-note {{here}} +struct Z {}; typedef int Integer; struct X { @@ -14,5 +14,5 @@ struct X { struct Y { enum E : int(2); - enum E : Z(); // expected-error{{not an integer constant}} expected-note {{non-constexpr constructor 'Z'}} + enum E : Z(); // expected-error{{not an integer constant}} }; |

