diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/CXX/basic/basic.types/p10.cpp | 108 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 37 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 125 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 188 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp | 74 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp | 28 |
6 files changed, 551 insertions, 9 deletions
diff --git a/test/CXX/basic/basic.types/p10.cpp b/test/CXX/basic/basic.types/p10.cpp new file mode 100644 index 0000000000..6618955235 --- /dev/null +++ b/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}} 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 e1911a2a79..9eaf35fc18 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -49,22 +49,41 @@ union U4 {} constexpr u4 = {}; enum E4 { V4 } constexpr e4 = V4; constexpr int; // expected-error {{constexpr can only be used in variable and function declarations}} // redeclaration mismatch -constexpr int f3(); // n -int f3(); // x -int f4(); // n -constexpr int f4(); // x +constexpr int f3(); // expected-note {{previous declaration is here}} +int f3(); // expected-error {{non-constexpr declaration of 'f3' follows constexpr declaration}} +int f4(); // expected-note {{previous declaration is here}} +constexpr int f4(); // expected-error {{constexpr declaration of 'f4' follows non-constexpr declaration}} +template<typename T> constexpr T f5(T); +template<typename T> constexpr T f5(T); // expected-note {{previous}} +template<typename T> T f5(T); // expected-error {{non-constexpr declaration of 'f5' follows constexpr declaration}} +template<typename T> T f6(T); // expected-note {{here}} +template<typename T> constexpr T f6(T); // expected-error {{constexpr declaration of 'f6' follows non-constexpr declaration}} // destructor struct ConstexprDtor { constexpr ~ConstexprDtor() = default; // expected-error {{destructor cannot be marked constexpr}} }; // template stuff -template <typename T> -constexpr T ft(T t) { return t; } +template <typename T> constexpr T ft(T t) { return t; } +template <typename T> T gt(T t) { return t; } +struct S { + template<typename T> constexpr T f(); + template<typename T> T g() const; +}; -// specialization can differ in constepxr -template <> -notlit ft(notlit nl) { return nl; } +// explicit specialization can differ in constepxr +// FIXME: When checking the explicit specialization, we implicitly instantiate +// the primary template then claim a constexpr mismatch. +template <> notlit ft(notlit nl) { return nl; } +template <> char ft(char c) { return c; } // desired-note {{previous}} unexpected-error {{follows constexpr declaration}} unexpected-note {{here}} +template <> constexpr char ft(char nl); // desired-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}} +template <> constexpr int gt(int nl) { return nl; } // unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}} +template <> notlit S::f() const { return notlit(); } +template <> constexpr int S::g() { return 0; } // desired-note {{previous}} unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}} +template <> int S::g() const; // desired-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}} +// specializations can drop the 'constexpr' but not the implied 'const'. +template <> char S::g() { return 0; } // expected-error {{no function template matches}} +template <> double S::g() const { return 0; } // ok // FIXME: The initializer is a constant expression. constexpr int i3 = ft(1); // unexpected-error {{must be initialized by a constant expression}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp new file mode 100644 index 0000000000..2a10b0832f --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -0,0 +1,125 @@ +// RUN: %clang_cc1 -verify -std=c++0x %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { // expected-note 4{{no constexpr constructors}} + NonLiteral() {} + NonLiteral(int) {} +}; +struct Literal { + constexpr Literal() {} + operator int() const { return 0; } +}; + +struct S { + virtual int ImplicitlyVirtual() const = 0; // expected-note {{overridden virtual function}} +}; +struct SS : S { + int ImplicitlyVirtual() const; +}; + +// Note, the wording applies constraints to the definition of constexpr +// functions, but we intentionally apply all that we can to the declaration +// instead. See DR1360. + +// The definition of a constexpr function shall satisfy the following +// constraints: +struct T : SS { // expected-note {{base class 'SS' of non-literal type}} + constexpr T(); // expected-error {{non-literal type 'T' cannot have constexpr members}} + + // - it shall not be virtual; + virtual constexpr int ExplicitlyVirtual(); // expected-error {{virtual function cannot be constexpr}} + + constexpr int ImplicitlyVirtual(); // expected-error {{virtual function cannot be constexpr}} + + // - its return type shall be a literal type; + constexpr NonLiteral NonLiteralReturn(); // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}} + typedef NonLiteral F(); + constexpr F NonLiteralReturn2; // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + + // - each of its parameter types shall be a literal type; + constexpr int NonLiteralParam(NonLiteral); // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + typedef int G(NonLiteral); + constexpr G NonLiteralParam2; // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + + // - its function-body shall be = delete, = default, + constexpr int Deleted() = delete; + // It's not possible for the function-body to legally be "= default" here. + // Other than constructors, only the copy- and move-assignment operators and + // destructor can be defaulted. Destructors can't be constexpr since they + // don't have a literal return type. Defaulted assignment operators can't be + // constexpr since they can't be const. + constexpr T &operator=(const T&) = default; // expected-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} +}; +struct U { + constexpr U SelfReturn(); + constexpr int SelfParam(U); +}; + +// or a compound-statememt that contains only +constexpr int AllowedStmts() { + // - null statements + ; + + // - static_assert-declarations + static_assert(true, "the impossible happened!"); + + // - typedef declarations and alias-declarations that do not define classes + // or enumerations + typedef int I; + typedef struct S T; + using J = int; + using K = int[sizeof(I) + sizeof(J)]; + // Note, the standard requires we reject this. + struct U; + + // - using-declarations + using N::C; + + // - using-directives + using namespace N; + + // - and exactly one return statement + return sizeof(K) + sizeof(C) + sizeof(K); +} +constexpr int ForStmt() { + for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr function}} + return 0; +} +constexpr int VarDecl() { + constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr function}} + return 0; +} +constexpr int FuncDecl() { + constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr function}} + return ForwardDecl(42); +} +constexpr int ClassDecl1() { + typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr function}} + return 0; +} +constexpr int ClassDecl2() { + using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr function}} + return 0; +} +constexpr int ClassDecl3() { + struct S3 { }; // expected-error {{types cannot be defined in a constexpr function}} + return 0; +} +constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}} +constexpr int MultiReturn() { + return 0; // expected-note {{return statement}} + return 0; // expected-error {{multiple return statements in constexpr function}} +} + +// - every constructor call and implicit conversion used in initializing the +// return value shall be one of those allowed in a constant expression. +// +// We implement the proposed resolution of DR1364 and ignore this bullet. diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp new file mode 100644 index 0000000000..4594f6cdb0 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -0,0 +1,188 @@ +// RUN: %clang_cc1 -verify -std=c++0x -fcxx-exceptions %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { // expected-note 2{{no constexpr constructors}} + NonLiteral() {} + NonLiteral(int) {} +}; +struct Literal { + constexpr Literal() {} + operator int() const { return 0; } +}; + +// Note, the wording applies constraints to the definition of constexpr +// constructors, but we intentionally apply all that we can to the declaration +// instead. See DR1360. + +// In the definition of a constexpr constructor, each of the parameter types +// shall be a literal type. +struct S { + constexpr S(int, N::C); + constexpr S(int, NonLiteral, N::C); // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + constexpr S(int, NonLiteral = 42); // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + + // In addition, either its function-body shall be = delete or = default + constexpr S() = default; + constexpr S(Literal) = delete; +}; + +// or it shall satisfy the following constraints: + +// - the class shall not have any virtual base classes; +struct T : virtual S { // expected-note {{here}} + constexpr T(); // expected-error {{constexpr constructor not allowed in struct with virtual base classes}} +}; +namespace IndirectVBase { + struct A {}; + struct B : virtual A {}; // expected-note {{here}} + class C : public B { + public: + constexpr C(); // expected-error {{constexpr constructor not allowed in class with virtual base classes}} + }; +} + +// - its function-body shall not be a function-try-block; +struct U { + constexpr U() + try // expected-error {{function try block not allowed in constexpr constructor}} + : u() { + } catch (...) { + throw; + } + int u; +}; + +// - the compound-statememt of its function-body shall contain only +struct V { + constexpr V() { + // - null statements, + ; + + // - static_assert-declarations, + static_assert(true, "the impossible happened!"); + + // - typedef declarations and alias-declarations that do not define classes + // or enumerations, + typedef int I; + typedef struct S T; + using J = int; + using K = int[sizeof(I) + sizeof(J)]; + // Note, the standard requires we reject this. + struct U; + + // - using-declarations, + using N::C; + + // - and using-directives; + using namespace N; + } + + constexpr V(int(&)[1]) { + for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr constructor}} + /**/; + } + constexpr V(int(&)[2]) { + constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr constructor}} + } + constexpr V(int(&)[3]) { + constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr constructor}} + } + constexpr V(int(&)[4]) { + typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr constructor}} + } + constexpr V(int(&)[5]) { + using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr constructor}} + } + constexpr V(int(&)[6]) { + struct S3 { }; // expected-error {{types cannot be defined in a constexpr constructor}} + } + constexpr V(int(&)[7]) { + return; // expected-error {{statement not allowed in constexpr constructor}} + } +}; + +// - every non-static data member and base class sub-object shall be initialized +struct W { + int n; // expected-note {{member not initialized by constructor}} + constexpr W() {} // expected-error {{constexpr constructor must initialize all members}} +}; +struct AnonMembers { + int a; // expected-note {{member not initialized by constructor}} + union { // expected-note 2{{member not initialized by constructor}} + char b; + struct { + double c; + long d; // expected-note {{member not initialized by constructor}} + }; + union { + char e; + void *f; + }; + }; + struct { // expected-note {{member not initialized by constructor}} + long long g; + struct { + int h; // expected-note {{member not initialized by constructor}} + double i; // expected-note {{member not initialized by constructor}} + }; + union { // expected-note 2{{member not initialized by constructor}} + char *j; + AnonMembers *k; + }; + }; + + constexpr AnonMembers(int(&)[1]) : a(), b(), g(), h(), i(), j() {} // ok + // missing d, i, j/k union + constexpr AnonMembers(int(&)[2]) : a(), c(), g(), h() {} // expected-error {{constexpr constructor must initialize all members}} + constexpr AnonMembers(int(&)[3]) : a(), e(), g(), h(), i(), k() {} // ok + // missing h, j/k union + constexpr AnonMembers(int(&)[4]) : a(), c(), d(), g(), i() {} // expected-error {{constexpr constructor must initialize all members}} + // missing b/c/d/e/f union + constexpr AnonMembers(int(&)[5]) : a(), g(), h(), i(), k() {} // expected-error {{constexpr constructor must initialize all members}} + // missing a, b/c/d/e/f union, g/h/i/j/k struct + constexpr AnonMembers(int(&)[6]) {} // expected-error {{constexpr constructor must initialize all members}} +}; + +// - every constructor involved in initializing non-static data members and base +// class sub-objects shall be a constexpr constructor. +// +// FIXME: Implement this as part of the 'must be able to produce a constant +// expression' rules. + +// - every assignment-expression that is an initializer-caluse appearing +// directly or indirectly within a brace-or-equal-initializer for a non-static +// data member that is not named by a mem-initializer-id shall be a constant +// expression; and +// +// Note, we deliberately do not implement this bullet, so that we can allow the +// following example. (See N3308). +struct X { + int a = 0; + int b = 2 * a + 1; // ok, not a constant expression. + + constexpr X() {} + constexpr X(int c) : a(c) {} // ok, b initialized by 2 * c + 1 +}; + +// - every implicit conversion used in converting a constructor argument to the +// corresponding parameter type and converting a full-expression to the +// corresponding member type shall be one of those allowed in a constant +// expression. +// +// We implement the proposed resolution of DR1364 and ignore this bullet. + + +namespace StdExample { + struct Length { + explicit constexpr Length(int i = 0) : val(i) { } + private: + int val; + }; +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp new file mode 100644 index 0000000000..ab45e92799 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -verify -std=c++0x %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { + NonLiteral() {} + NonLiteral(int) {} + operator int() const { return 0; } +}; +struct Literal { + constexpr Literal() {} + operator int() const { return 0; } +}; + +struct S { + virtual int ImplicitlyVirtual(); +}; +struct T {}; + +template<typename T> struct ImplicitVirtualFromDependentBase : T { + constexpr int ImplicitlyVirtual() { return 0; } +}; + +// FIXME: Can't test this until we have function invocation substitution +#if 0 +constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // desired-error {{not a constant expression}} +constexpr int b = ImplicitVirtualFromDependentBase<T>().ImplicitlyVirtual(); // ok +#endif + +template<typename R> struct ConstexprMember { + constexpr R F() { return 0; } +}; +// FIXME: Can't test this until we have function invocation substitution +#if 0 +constexpr int c = ConstexprMember<int>().F(); // ok +constexpr int d = ConstexprMember<NonLiteral>().F(); // desired-error {{not a constant expression}} +#endif + +template<typename ...P> struct ConstexprCtor { // expected-note 2{{no constexpr constructors}} + constexpr ConstexprCtor(P...); // expected-note {{constructor template instantiation is not constexpr because 1st parameter type 'NonLiteral' is not a literal type}} \ + expected-note {{constructor template instantiation is not constexpr because 2nd parameter type 'NonLiteral' is not a literal type}} +}; +constexpr ConstexprCtor<> f1(); // ok +constexpr ConstexprCtor<int> f2(); // ok +constexpr ConstexprCtor<NonLiteral> f3(); // expected-error {{not a literal type}} +constexpr ConstexprCtor<int, NonLiteral> f4(); // expected-error {{not a literal type}} + +struct VirtBase : virtual S {}; // expected-note {{here}} + +namespace TemplateVBase { + template<typename T> struct T1 : virtual Literal { // expected-note {{here}} + constexpr T1(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}} + }; + + template<typename T> struct T2 : virtual T { // expected-note {{struct with virtual base class is not a literal type}} expected-note {{here}} + // FIXME: This is ill-formed (no diagnostic required). + // We should diagnose it now rather than waiting until instantiation. + constexpr T2(); // desired-error {{constexpr constructor not allowed in class with virtual base classes}} + }; + constexpr T2<Literal> g2(); // expected-error {{not a literal type}} + + template<typename T> class T3 : public T { // expected-note {{class with virtual base class is not a literal type}} + public: + constexpr T3() {} + }; + constexpr T3<Literal> g3(); // ok + constexpr T3<VirtBase> g4(); // expected-error {{not a literal type}} +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp new file mode 100644 index 0000000000..a5c21e8f37 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +struct S { + constexpr void f(); + constexpr void g() const; +}; + +void f(const S &s) { + s.f(); + s.g(); +} + +namespace std_example { + + class debug_flag { // expected-note {{not an aggregate and has no constexpr constructors}} + public: + explicit debug_flag(bool); + constexpr bool is_on(); // expected-error {{non-literal type 'std_example::debug_flag' cannot have constexpr members}} + private: + bool flag; + }; + + constexpr int bar(int x, int y) // expected-note {{here}} + { return x + y + x*y; } + int bar(int x, int y) // expected-error {{non-constexpr declaration of 'bar' follows constexpr declaration}} + { return x * 2 + 3 * y; } + +} |