diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-01 02:31:28 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-01 02:31:28 +0000 |
| commit | eb3c10c248ace4100f54e8fb55b7d477d959f222 (patch) | |
| tree | 2e491475a9d346831848214fba8721e7a53863e7 /clang/test/CXX/basic | |
| parent | c5ab7efea372bb2ab025e3a6168766237f9c0de7 (diff) | |
| download | bcm5719-llvm-eb3c10c248ace4100f54e8fb55b7d477d959f222.tar.gz bcm5719-llvm-eb3c10c248ace4100f54e8fb55b7d477d959f222.zip | |
constexpr: semantic checking for constexpr functions and constructors. Based in
part on patches by Peter Collingbourne.
We diverge from the C++11 standard in a few areas, mostly related to checking
constexpr function declarations, and not just definitions. See WG21 paper
N3308=11-0078 for details.
Function invocation substitution is not available in this patch; constexpr
functions cannot yet be used from within constant expressions.
llvm-svn: 140926
Diffstat (limited to 'clang/test/CXX/basic')
| -rw-r--r-- | clang/test/CXX/basic/basic.types/p10.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/clang/test/CXX/basic/basic.types/p10.cpp b/clang/test/CXX/basic/basic.types/p10.cpp new file mode 100644 index 00000000000..66189552350 --- /dev/null +++ b/clang/test/CXX/basic/basic.types/p10.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +struct NonLiteral { NonLiteral(); }; + +// A type is a literal type if it is: + +// - a scalar type +constexpr int f1(double); + +// - a reference type +struct S { S(); }; +constexpr int f2(S &); + +// - a class type that has all of the following properties: + +// - it has a trivial destructor +struct UserProvDtor { + constexpr UserProvDtor(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} + ~UserProvDtor(); // expected-note {{has a user-provided destructor}} +}; +struct NonTrivDtor { + constexpr NonTrivDtor(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} + virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} +}; +struct NonTrivDtorBase { + ~NonTrivDtorBase(); +}; +template<typename T> +struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} + constexpr DerivedFromNonTrivDtor(); +}; +constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} +struct TrivDtor { + constexpr TrivDtor(); +}; +// FIXME: when building DefinitionData we look at 'isUserProvided' before it's set up! +#if 0 +struct TrivDefaultedDtor { + constexpr TrivDefaultedDtor(); + ~TrivDefaultedDtor() = default; +}; +#endif + +// - it is an aggregate type or has at least one constexpr constructor or +// constexpr constructor template that is not a copy or move constructor +struct Agg { + int a; + char *b; +}; +constexpr int f3(Agg a) { return a.a; } +struct CtorTemplate { + template<typename T> constexpr CtorTemplate(T); +}; +struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + constexpr CopyCtorOnly(CopyCtorOnly&); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}} +}; +struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} + constexpr MoveCtorOnly(MoveCtorOnly&&); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}} +}; +template<typename T> +struct CtorArg { // expected-note {{no constexpr constructors other than copy or move constructors}} + constexpr CtorArg(T); // expected-note {{constructor template instantiation is not constexpr because 1st parameter type 'NonLiteral' is not a literal type}} +}; +constexpr int f(CtorArg<int>); +constexpr int f(CtorArg<NonLiteral>); // expected-error {{not a literal type}} +// We have a special-case diagnostic for classes with virtual base classes. +struct VBase {}; +struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}} +struct Derived : HasVBase { + constexpr Derived(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}} +}; +template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} + constexpr DerivedFromVBase(); +}; +constexpr int f(DerivedFromVBase<HasVBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} + +// - it has all non-static data members and base classes of literal types +struct NonLitMember { + S s; // expected-note {{has data member 's' of non-literal type 'S'}} +}; +constexpr int f(NonLitMember); // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} +struct NonLitBase : + S { // expected-note {{base class 'S' of non-literal type}} + constexpr NonLitBase(); // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}} +}; +struct LitMemBase : Agg { + Agg agg; +}; +template<typename T> +struct MemberType { + T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}} + constexpr MemberType(); +}; +constexpr int f(MemberType<int>); +constexpr int f(MemberType<NonLiteral>); // expected-error {{not a literal type}} + +// - an array of literal type +struct ArrGood { + Agg agg[24]; + double d[12]; + TrivDtor td[3]; +}; +constexpr int f(ArrGood); + +struct ArrBad { + S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}} +}; +constexpr int f(ArrBad); // expected-error {{1st parameter type 'ArrBad' is not a literal type}} |

