summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/expr/expr.const/p2-0x.cpp26
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx11.cpp39
-rw-r--r--clang/test/SemaCXX/constexpr-turing.cpp55
3 files changed, 92 insertions, 28 deletions
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index a22d1e4e4e3..8d3638ffc6b 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -49,25 +49,23 @@ struct UndefinedConstexpr {
};
// - an invocation of a constexpr function with arguments that, when substituted
-// by function invocation substitution (7.1.5), do not produce a constant
+// by function invocation substitution (7.1.5), do not produce a core constant
// expression;
namespace NonConstExprReturn {
static constexpr const int &id_ref(const int &n) {
- return n; // expected-note {{reference to temporary cannot be returned from a constexpr function}}
+ return n;
}
struct NonConstExprFunction {
- int n : id_ref( // expected-error {{constant expression}} expected-note {{in call to 'id_ref(16)'}}
- 16 // expected-note {{temporary created here}}
- );
+ int n : id_ref(16); // ok
};
constexpr const int *address_of(const int &a) {
- return &a; // expected-note {{pointer to 'n' cannot be returned from a constexpr function}}
+ return &a;
}
constexpr const int *return_param(int n) { // expected-note {{declared here}}
- return address_of(n); // expected-note {{in call to 'address_of(n)'}}
+ return address_of(n);
}
struct S {
- int n : *return_param(0); // expected-error {{constant expression}} expected-note {{in call to 'return_param(0)'}}
+ int n : *return_param(0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}}
};
}
@@ -78,16 +76,16 @@ namespace NonConstExprReturn {
namespace NonConstExprCtor {
struct T {
constexpr T(const int &r) :
- r(r) { // expected-note 2{{reference to temporary cannot be used to initialize a member in a constant expression}}
+ r(r) {
}
const int &r;
};
constexpr int n = 0;
constexpr T t1(n); // ok
- constexpr T t2(0); // expected-error {{must be initialized by a constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'T(0)'}}
+ constexpr T t2(0); // expected-error {{must be initialized by a constant expression}} expected-note {{temporary created here}} expected-note {{reference to temporary is not a constant expression}}
struct S {
- int n : T(4).r; // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'T(4)'}}
+ int n : T(4).r; // ok
};
}
@@ -176,12 +174,12 @@ namespace UndefinedBehavior {
struct S {
int m;
};
- constexpr S s = { 5 }; // expected-note {{declared here}}
+ constexpr S s = { 5 };
constexpr const int *p = &s.m + 1;
constexpr const int &f(const int *q) {
- return q[0]; // expected-note {{dereferenced pointer past the end of subobject of 's' is not a constant expression}}
+ return q[0];
}
- constexpr int n = (f(p), 0); // expected-error {{constant expression}} expected-note {{in call to 'f(&s.m + 1)'}}
+ constexpr int n = (f(p), 0); // ok
struct T {
int n : f(p); // expected-error {{not an integral constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
};
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 58f36fdf9c8..aa4031189d8 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -190,26 +190,21 @@ namespace StaticMemberFunction {
namespace ParameterScopes {
const int k = 42;
- constexpr const int &ObscureTheTruth(const int &a) { return a; } // expected-note 3{{reference to 'a' cannot be returned from a constexpr function}}
+ constexpr const int &ObscureTheTruth(const int &a) { return a; }
constexpr const int &MaybeReturnJunk(bool b, const int a) { // expected-note 2{{declared here}}
- return ObscureTheTruth(b ? a : k); // expected-note 2{{in call to 'ObscureTheTruth(a)'}}
+ return ObscureTheTruth(b ? a : k);
}
static_assert(MaybeReturnJunk(false, 0) == 42, ""); // ok
- constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{in call to 'MaybeReturnJunk(1, 0)'}}
+ constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}}
- constexpr const int MaybeReturnNonstaticRef(bool b, const int a) { // expected-note {{here}}
- // If ObscureTheTruth returns a reference to 'a', the result is not a
- // constant expression even though 'a' is still in scope.
- return ObscureTheTruth(b ? a : k); // expected-note {{in call to 'ObscureTheTruth(a)'}}
+ constexpr const int MaybeReturnNonstaticRef(bool b, const int a) {
+ return ObscureTheTruth(b ? a : k);
}
static_assert(MaybeReturnNonstaticRef(false, 0) == 42, ""); // ok
- constexpr int b = MaybeReturnNonstaticRef(true, 0); // expected-error {{constant expression}} expected-note {{in call to 'MaybeReturnNonstaticRef(1, 0)'}}
+ constexpr int b = MaybeReturnNonstaticRef(true, 0); // ok
constexpr int InternalReturnJunk(int n) {
- // TODO: We could reject this: it never produces a constant expression.
- // However, we currently don't evaluate function calls while testing for
- // potential constant expressions, for performance.
- return MaybeReturnJunk(true, n); // expected-note {{in call to 'MaybeReturnJunk(1, 0)'}}
+ return MaybeReturnJunk(true, n); // expected-note {{read of variable whose lifetime has ended}}
}
constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'InternalReturnJunk(0)'}}
@@ -528,10 +523,10 @@ struct D {
static_assert(D().c.n == 42, "");
struct E {
- constexpr E() : p(&p) {} // expected-note {{pointer to subobject of temporary cannot be used to initialize a member in a constant expression}}
+ constexpr E() : p(&p) {}
void *p;
};
-constexpr const E &e1 = E(); // expected-error {{constant expression}} expected-note {{in call to 'E()'}} expected-note {{temporary created here}}
+constexpr const E &e1 = E(); // expected-error {{constant expression}} expected-note {{reference to temporary is not a constant expression}} expected-note {{temporary created here}}
// This is a constant expression if we elide the copy constructor call, and
// is not a constant expression if we don't! But we do, so it is.
constexpr E e2 = E();
@@ -1158,3 +1153,19 @@ namespace Fold {
#undef fold
}
+
+namespace DR1454 {
+
+constexpr const int &f(const int &n) { return n; }
+constexpr int k1 = f(0); // ok
+
+struct Wrap {
+ const int &value;
+};
+constexpr const Wrap &g(const Wrap &w) { return w; }
+constexpr int k2 = g({0}).value; // ok
+
+constexpr const int &i = 0; // expected-error {{constant expression}} expected-note {{temporary}} expected-note 2{{here}}
+constexpr const int j = i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}}
+
+}
diff --git a/clang/test/SemaCXX/constexpr-turing.cpp b/clang/test/SemaCXX/constexpr-turing.cpp
new file mode 100644
index 00000000000..c5153788adf
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-turing.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+// A direct proof that constexpr is Turing-complete, once DR1454 is implemented.
+
+const unsigned halt = (unsigned)-1;
+
+enum Dir { L, R };
+struct Action {
+ bool tape;
+ Dir dir;
+ unsigned next;
+};
+using State = Action[2];
+
+// An infinite tape!
+struct Tape {
+ constexpr Tape() : l(0), val(false), r(0) {}
+ constexpr Tape(const Tape &old, bool write) :
+ l(old.l), val(write), r(old.r) {}
+ constexpr Tape(const Tape &old, Dir dir) :
+ l(dir == L ? old.l ? old.l->l : 0 : &old),
+ val(dir == L ? old.l ? old.l->val : false
+ : old.r ? old.r->val : false),
+ r(dir == R ? old.r ? old.r->r : 0 : &old) {}
+ const Tape *l;
+ bool val;
+ const Tape *r;
+};
+constexpr Tape update(const Tape &old, bool write) { return Tape(old, write); }
+constexpr Tape move(const Tape &old, Dir dir) { return Tape(old, dir); }
+
+// Run turing machine 'tm' on tape 'tape' from state 'state'. Return number of
+// steps taken until halt.
+constexpr unsigned run(const State *tm, const Tape &tape, unsigned state) {
+ return state == halt ? 1 :
+ run(tm, move(update(tape, tm[state][tape.val].tape),
+ tm[state][tape.val].dir),
+ tm[state][tape.val].next) + 1;
+}
+
+// 3-state busy beaver. 14 steps.
+constexpr State bb3[] = {
+ { { true, R, 1 }, { true, L, 2 } },
+ { { true, L, 0 }, { true, R, 1 } },
+ { { true, L, 1 }, { true, R, halt } }
+};
+static_assert(run(bb3, Tape(), 0) == 14, "");
+
+// 4-state busy beaver. 108 steps.
+constexpr State bb4[] = {
+ { { true, R, 1 }, { true, L, 1 } },
+ { { true, L, 0 }, { false, L, 2 } },
+ { { true, R, halt }, { true, L, 3 } },
+ { { true, R, 3 }, { false, R, 0 } } };
+static_assert(run(bb4, Tape(), 0) == 108, "");
OpenPOWER on IntegriCloud