diff options
Diffstat (limited to 'clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr')
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 123 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp | 26 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 139 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 249 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp | 112 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp | 68 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp | 38 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp | 37 |
8 files changed, 792 insertions, 0 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 new file mode 100644 index 0000000..6820fc6 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct notlit { // expected-note {{not literal because}} + notlit() {} +}; +struct notlit2 { + notlit2() {} +}; + +// valid declarations +constexpr int i1 = 0; +constexpr int f1() { return 0; } +struct s1 { + constexpr static int mi1 = 0; + const static int mi2; +}; +constexpr int s1::mi2 = 0; + +// invalid declarations +// not a definition of an object +constexpr extern int i2; // expected-error {{constexpr variable declaration must be a definition}} +// not a literal type +constexpr notlit nl1; // expected-error {{constexpr variable cannot have non-literal type 'const notlit'}} +// function parameters +void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}} +// non-static member +struct s2 { + constexpr int mi1; // expected-error {{non-static data member cannot be constexpr}} + static constexpr int mi2; // expected-error {{requires an initializer}} +}; +// typedef +typedef constexpr int CI; // expected-error {{typedef cannot be constexpr}} +// tag +constexpr class C1 {}; // expected-error {{class cannot be marked constexpr}} +constexpr struct S1 {}; // expected-error {{struct cannot be marked constexpr}} +constexpr union U1 {}; // expected-error {{union cannot be marked constexpr}} +constexpr enum E1 {}; // expected-error {{enum cannot be marked constexpr}} +template <typename T> constexpr class TC1 {}; // expected-error {{class cannot be marked constexpr}} +template <typename T> constexpr struct TS1 {}; // expected-error {{struct cannot be marked constexpr}} +template <typename T> constexpr union TU1 {}; // expected-error {{union cannot be marked constexpr}} +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}} +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(); +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}} +// redeclaration mismatch +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> T gt(T t) { return t; } +struct S { + template<typename T> constexpr T f(); + template<typename T> T g() const; +}; + +// explicit specialization can differ in constepxr +template <> notlit ft(notlit nl) { return nl; } +template <> char ft(char c) { return c; } // expected-note {{previous}} +template <> constexpr char ft(char nl); // expected-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}} +template <> constexpr int gt(int nl) { return nl; } +template <> notlit S::f() const { return notlit(); } +template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> int S::g() const; // expected-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 + +constexpr int i3 = ft(1); + +void test() { + // ignore constexpr when instantiating with non-literal + notlit2 nl2; + (void)ft(nl2); +} + +// Examples from the standard: +constexpr int square(int x); // expected-note {{declared here}} +constexpr int bufsz = 1024; + +constexpr struct pixel { // expected-error {{struct cannot be marked constexpr}} + int x; + int y; + constexpr pixel(int); +}; + +constexpr pixel::pixel(int a) + : x(square(a)), y(square(a)) // expected-note {{undefined function 'square' cannot be used in a constant expression}} + { } + +constexpr pixel small(2); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'pixel(2)'}} + +constexpr int square(int x) { + return x * x; +} + +constexpr pixel large(4); + +int next(constexpr int x) { // expected-error {{function parameter cannot be constexpr}} + return x + 1; +} + +extern constexpr int memsz; // expected-error {{constexpr variable declaration must be a definition}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp new file mode 100644 index 0000000..001a086 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - | FileCheck %s + +// constexpr functions and constexpr constructors are implicitly inline. +struct S { + constexpr S(int n); + constexpr int g(); + int n; +}; + +constexpr S::S(int n) : n(n) {} + +constexpr S f(S s) { + return s.n * 2; +} + +constexpr int S::g() { + return f(*this).n; +} + +// CHECK: define linkonce_odr {{.*}} @_Z1f1S( +// CHECK: define linkonce_odr {{.*}} @_ZN1SC1Ei( +// CHECK: define linkonce_odr {{.*}} @_ZNK1S1gEv( + +int g() { + return f(42).g(); +} 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 new file mode 100644 index 0000000..cafdd63 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -verify -std=c++11 %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; } +}; + +struct S { + virtual int ImplicitlyVirtual() const = 0; // expected-note {{overridden virtual function}} +}; +struct SS : S { + int ImplicitlyVirtual() const; +}; + +// The definition of a constexpr function shall satisfy the following +// constraints: +struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}} + constexpr T(); + constexpr int f(); // expected-error {{non-literal type 'T' cannot have constexpr members}} + + // - it shall not be virtual; + virtual constexpr int ExplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}} + + constexpr int ImplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}} + + // - its return type shall be a literal type; + constexpr NonLiteral NonLiteralReturn() { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr void VoidReturn() { return; } // expected-error {{constexpr function's return type 'void' is not a literal type}} + constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}} + typedef NonLiteral F(); + constexpr F NonLiteralReturn2; // ok until definition + + // - each of its parameter types shall be a literal type; + constexpr int NonLiteralParam(NonLiteral) { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + typedef int G(NonLiteral); + constexpr G NonLiteralParam2; // ok until definition + + // - 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); +}; + +struct V : virtual U { // expected-note {{here}} + constexpr int F() { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}} +}; + +// 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. +// However, we implement the spirit of the check as part of the p5 checking that +// a constexpr function must be able to produce a constant expression. +namespace DR1364 { + constexpr int f(int k) { + return k; // ok, even though lvalue-to-rvalue conversion of a function + // parameter is not allowed in a constant expression. + } + int kGlobal; // expected-note {{here}} + constexpr int f() { // expected-error {{constexpr function never produces a constant expression}} + return kGlobal; // expected-note {{read of non-const}} + } +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp new file mode 100644 index 0000000..65573c7 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -0,0 +1,249 @@ +// RUN: %clang_cc1 -verify -std=c++11 -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() {} + explicit Literal(int); // expected-note 2 {{here}} + operator int() const { return 0; } +}; + +// 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 class}} +}; +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 class}} + }; +} + +// - 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}} +}; + +union Empty { + constexpr Empty() {} // ok +} constexpr empty1; + +struct EmptyVariant { + union {}; + struct {}; + constexpr EmptyVariant() {} // ok +} constexpr empty2; + +template<typename T> using Int = int; +template<typename T> +struct TemplateInit { + T a; + int b; // desired-note {{not initialized}} + Int<T> c; // desired-note {{not initialized}} + struct { + T d; + int e; // desired-note {{not initialized}} + Int<T> f; // desired-note {{not initialized}} + }; + struct { + Literal l; + Literal m; + Literal n[3]; + }; + union { // desired-note {{not initialized}} + T g; + T h; + }; + // FIXME: This is ill-formed (no diagnostic required). We should diagnose it. + constexpr TemplateInit() {} // desired-error {{must initialize all members}} +}; +template<typename T> struct TemplateInit2 { + Literal l; + constexpr TemplateInit2() {} // ok +}; + +template<typename T> struct weak_ptr { + constexpr weak_ptr() : p(0) {} + T *p; +}; +template<typename T> struct enable_shared_from_this { + weak_ptr<T> weak_this; + constexpr enable_shared_from_this() {} // ok +}; +constexpr int f(enable_shared_from_this<int>); + +// - every constructor involved in initializing non-static data members and base +// class sub-objects shall be a constexpr constructor. +struct ConstexprBaseMemberCtors : Literal { + Literal l; + + constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok + constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}} + Literal(0), // expected-note {{non-constexpr constructor}} + l() {} + constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}} + l(0) // expected-note {{non-constexpr constructor}} + {} +}; + +// - 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. +// However, we implement the intent of this wording as part of the p5 check that +// the function must be able to produce a constant expression. +int kGlobal; // expected-note {{here}} +struct Z { + constexpr Z(int a) : n(a) {} + constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} + int n; +}; + + +namespace StdExample { + struct Length { + explicit constexpr Length(int i = 0) : val(i) { } + private: + int val; + }; +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp new file mode 100644 index 0000000..fd17d35 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s + +namespace StdExample { + +constexpr int f(void *) { return 0; } +constexpr int f(...) { return 1; } +constexpr int g1() { return f(0); } +constexpr int g2(int n) { return f(n); } +constexpr int g3(int n) { return f(n*0); } + +namespace N { + constexpr int c = 5; + constexpr int h() { return c; } +} +constexpr int c = 0; +constexpr int g4() { return N::h(); } + +static_assert(f(0) == 0, ""); +static_assert(f('0') == 1, ""); +static_assert(g1() == 0, ""); +static_assert(g2(0) == 1, ""); +static_assert(g2(1) == 1, ""); +static_assert(g3(0) == 1, ""); +static_assert(g3(1) == 1, ""); +static_assert(N::h() == 5, ""); +static_assert(g4() == 5, ""); + + +constexpr int f(bool b) + { return b ? throw 0 : 0; } // ok +constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}} + +struct B { + constexpr B(int x) : i(0) { } + int i; +}; + +int global; // expected-note {{declared here}} + +struct D : B { + constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} +}; + +} + +namespace PotentialConstant { + +constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}} + (void)(n * 2), + throw 0, // expected-note {{subexpression}} + 0; +} + +int ng; // expected-note 6{{here}} +constexpr int BinaryOp1(int n) { return n + ng; } // expected-error {{never produces}} expected-note {{read}} +constexpr int BinaryOp2(int n) { return ng + n; } // expected-error {{never produces}} expected-note {{read}} + +double dg; // expected-note 2{{here}} +constexpr double BinaryOp1(double d) { return d + dg; } // expected-error {{never produces}} expected-note {{read}} +constexpr double BinaryOp2(double d) { return dg + d; } // expected-error {{never produces}} expected-note {{read}} + +constexpr int Add(int a, int b, int c) { return a + b + c; } +constexpr int FunctionArgs(int a) { return Add(a, ng, a); } // expected-error {{never produces}} expected-note {{read}} + +struct S { int a; int b; int c[2]; }; +constexpr S InitList(int a) { return { a, ng }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList1a(int a) { return S{ a, ng }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList2(int a) { return { a, a, { ng } }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList3(int a) { return a ? S{ a, a } : S{ a, ng }; }; // ok + +constexpr int LogicalAnd1(int n) { return n && (throw, 0); } // ok +constexpr int LogicalAnd2(int n) { return 1 && (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}} + +constexpr int LogicalOr1(int n) { return n || (throw, 0); } // ok +constexpr int LogicalOr2(int n) { return 0 || (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}} + +constexpr int Conditional1(bool b, int n) { return b ? n : ng; } // ok +constexpr int Conditional2(bool b, int n) { return b ? n * ng : n + ng; } // expected-error {{never produces}} expected-note {{both arms of conditional operator are unable to produce a constant expression}} + +// __builtin_constant_p ? : is magical, and is always a potential constant. +constexpr bool BcpCall(int n) { + return __builtin_constant_p((int*)n != &n) ? (int*)n != &n : (int*)n != &n; +} +static_assert(BcpCall(0), ""); + +// DR1311: A function template which can produce a constant expression, but +// for which a particular specialization cannot, is ok. +template<typename T> constexpr T cmin(T a, T b) { + return a < b ? a : b; +} +int n = cmin(3, 5); // ok + +struct X { + constexpr X() {} + bool operator<(X); // not constexpr +}; + +X x = cmin(X(), X()); // ok, not constexpr + +// Same with other temploids. +template<typename T> +struct Y { + constexpr Y() {} + constexpr int get() { return T(); } +}; +struct Z { operator int(); }; + +int y1 = Y<int>().get(); // ok +int y2 = Y<Z>().get(); // ok + +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp new file mode 100644 index 0000000..1a6dc9e --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { + NonLiteral() {} + NonLiteral(int) {} // expected-note 2{{here}} + operator int() const { return 0; } +}; +struct Literal { + constexpr Literal() {} + operator int() const { return 0; } +}; + +struct S { + virtual int ImplicitlyVirtual() const; +}; +struct T {}; + +template<typename T> struct ImplicitVirtualFromDependentBase : T { + constexpr int ImplicitlyVirtual() { return 0; } +}; + +constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate virtual function call}} +constexpr int b = ImplicitVirtualFromDependentBase<T>().ImplicitlyVirtual(); // ok +constexpr int c = ImplicitVirtualFromDependentBase<S>().ImplicitVirtualFromDependentBase<S>::ImplicitlyVirtual(); + +template<typename R> struct ConstexprMember { + constexpr R F() { return 0; } +}; +constexpr int d = ConstexprMember<int>().F(); // ok +constexpr int e = ConstexprMember<NonLiteral>().F(); // expected-error {{constant expression}} + +template<typename ...P> struct ConstexprCtor { + constexpr ConstexprCtor(P...) {} +}; +constexpr ConstexprCtor<> f1() { return {}; } // ok +constexpr ConstexprCtor<int> f2() { return 0; } // ok +constexpr ConstexprCtor<NonLiteral> f3() { return { 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}} +constexpr ConstexprCtor<int, NonLiteral> f4() { return { 0, 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}} + +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 { + // FIXME: This is ill-formed (no diagnostic required). + // We should diagnose it now rather than waiting until instantiation. + constexpr T2() {} + }; + constexpr T2<Literal> g2() { return {}; } + + 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() { return {}; } // ok + constexpr T3<VirtBase> g4() { return {}; } // expected-error {{not a literal type}} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp new file mode 100644 index 0000000..c4935b3 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + constexpr int f(); + constexpr int g() const; + static constexpr int Sf(); +}; + +void f(const S &s) { + s.f(); + s.g(); + + int (*f)() = &S::Sf; + int (S::*g)() const = &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; } + +} + +// The constexpr specifier is allowed for static member functions of non-literal types. +class NonLiteralClass { + NonLiteralClass(bool); + static constexpr bool isDebugFlag(); +}; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp new file mode 100644 index 0000000..2412a14 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// A constexpr specifier used in an object declaration declares the object as +// const. +constexpr int a = 0; +extern const int a; + +int i; // expected-note 2{{here}} +constexpr int *b = &i; +extern int *const b; + +constexpr int &c = i; +extern int &c; + +constexpr int (*d)(int) = 0; +extern int (*const d)(int); + +// A variable declaration which uses the constexpr specifier shall have an +// initializer and shall be initialized by a constant expression. +constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}} +constexpr struct C { C(); } ni2; // expected-error {{cannot have non-literal type 'const struct C'}} expected-note 3{{has no constexpr constructors}} +constexpr double &ni3; // expected-error {{declaration of reference variable 'ni3' requires an initializer}} + +constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +constexpr C nc2 = C(); // expected-error {{cannot have non-literal type 'const C'}} +int &f(); // expected-note {{declared here}} +constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +constexpr C nc5((C())); // expected-error {{cannot have non-literal type 'const C'}} +int &f(); // expected-note {{here}} +constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}} + +struct pixel { + int x, y; +}; +constexpr pixel ur = { 1294, 1024 }; // ok +constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' requires a user-provided default constructor}} |