diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 03:54:03 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 03:54:03 +0000 |
commit | 86c3ae46250cdcc57778c27826060779a92f3815 (patch) | |
tree | 0d448fb2248c76e1339de8ad2c8c28d2b08d9b14 /test/SemaCXX | |
parent | 9b338a7bca39a68ae9f8c57d9210f19f7e45b665 (diff) |
Update constexpr implementation to match CWG's chosen approach for core issues
1358, 1360, 1452 and 1453.
- Instantiations of constexpr functions are always constexpr. This removes the
need for separate declaration/definition checking, which is now gone.
- This makes it possible for a constexpr function to be virtual, if they are
only dependently virtual. Virtual calls to such functions are not constant
expressions.
- Likewise, it's now possible for a literal type to have virtual base classes.
A constexpr constructor for such a type cannot actually produce a constant
expression, though, so add a special-case diagnostic for a constructor call
to such a type rather than trying to evaluate it.
- Classes with trivial default constructors (for which value initialization can
produce a fully-initialized value) are considered literal types.
- Classes with volatile members are not literal types.
- constexpr constructors can be members of non-literal types. We do not yet use
static initialization for global objects constructed in this way.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150359 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaCXX')
-rw-r--r-- | test/SemaCXX/constexpr-value-init.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/literal-type.cpp | 28 |
2 files changed, 18 insertions, 12 deletions
diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp index efa9e94da1..db4b68dcc6 100644 --- a/test/SemaCXX/constexpr-value-init.cpp +++ b/test/SemaCXX/constexpr-value-init.cpp @@ -26,6 +26,6 @@ struct D : C { int d; }; constexpr C c1; // expected-error {{requires a user-provided default constructor}} constexpr C c2 = C(); // ok constexpr D d1; // expected-error {{requires a user-provided default constructor}} -constexpr D d2 = D(); // expected-error {{constant expression}} expected-note {{non-literal type 'const D'}} +constexpr D d2 = D(); // ok with DR1452 static_assert(D().c == 0, ""); static_assert(D().d == 0, ""); diff --git a/test/SemaCXX/literal-type.cpp b/test/SemaCXX/literal-type.cpp index 60bfcf00cf..14a4094c45 100644 --- a/test/SemaCXX/literal-type.cpp +++ b/test/SemaCXX/literal-type.cpp @@ -23,6 +23,8 @@ static_assert(__is_literal(VectorExt), "fail"); // a constant expression, // -- it is an aggregate type or has at least one constexpr constructor // or constructor template that is not a copy or move constructor, and +// [DR1452 adds class types with trivial default constructors to +// this list] // -- it has all non-static data members and base classes of literal // types struct Empty {}; @@ -36,25 +38,26 @@ struct LiteralType { struct HasDtor { ~HasDtor(); }; class NonAggregate { int x; }; -struct HasNonLiteralBase : NonAggregate {}; +struct NonLiteral { NonLiteral(); }; +struct HasNonLiteralBase : NonLiteral {}; struct HasNonLiteralMember { HasDtor x; }; static_assert(__is_literal(Empty), "fail"); static_assert(__is_literal(LiteralType), "fail"); +static_assert(__is_literal(NonAggregate), "fail"); +static_assert(!__is_literal(NonLiteral), "fail"); static_assert(!__is_literal(HasDtor), "fail"); -static_assert(!__is_literal(NonAggregate), "fail"); static_assert(!__is_literal(HasNonLiteralBase), "fail"); static_assert(!__is_literal(HasNonLiteralMember), "fail"); -// FIXME: Test constexpr constructors and non-static members with initializers -// when Clang supports them: -#if 0 -extern int f(); +// DR1361 removes the brace-or-equal-initializer bullet so that we can allow: +extern int f(); // expected-note {{here}} struct HasNonConstExprMemInit { - int x = f(); - constexpr HasNonConstExprMemInit(int y) {} + int x = f(); // expected-note {{non-constexpr function}} + constexpr HasNonConstExprMemInit() {} // expected-error {{never produces a constant expression}} + constexpr HasNonConstExprMemInit(int y) : x(y) {} // ok }; -static_assert(!__is_literal(HasNonConstExprMemInit), "fail"); +static_assert(__is_literal(HasNonConstExprMemInit), "fail"); class HasConstExprCtor { int x; @@ -66,6 +69,9 @@ template <typename T> class HasConstExprCtorTemplate { public: template <typename U> constexpr HasConstExprCtorTemplate(U y) : x(y) {} }; +template <typename T> class HasConstExprCtorT { + constexpr HasConstExprCtorT(T) {} +}; static_assert(__is_literal(HasConstExprCtor), "fail"); -static_assert(__is_literal(HasConstExprCtorTemplate), "fail"); -#endif +static_assert(__is_literal(HasConstExprCtorTemplate<int>), "fail"); +static_assert(__is_literal(HasConstExprCtorT<NonLiteral>), "fail"); |