aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CXX/basic/basic.types/p10.cpp108
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp37
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp125
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp188
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp74
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp28
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; }
+
+}