1b228a86fSRichard Smith // RUN: %clang_cc1 -verify -std=c++11 %s
2c6e68daaSAndy Gibbs // expected-no-diagnostics
3b228a86fSRichard Smith
4b228a86fSRichard Smith // A direct proof that constexpr is Turing-complete, once DR1454 is implemented.
5b228a86fSRichard Smith
6b228a86fSRichard Smith const unsigned halt = (unsigned)-1;
7b228a86fSRichard Smith
8b228a86fSRichard Smith enum Dir { L, R };
9b228a86fSRichard Smith struct Action {
10b228a86fSRichard Smith bool tape;
11b228a86fSRichard Smith Dir dir;
12b228a86fSRichard Smith unsigned next;
13b228a86fSRichard Smith };
14b228a86fSRichard Smith using State = Action[2];
15b228a86fSRichard Smith
16b228a86fSRichard Smith // An infinite tape!
17b228a86fSRichard Smith struct Tape {
TapeTape18b228a86fSRichard Smith constexpr Tape() : l(0), val(false), r(0) {}
TapeTape19b228a86fSRichard Smith constexpr Tape(const Tape &old, bool write) :
20b228a86fSRichard Smith l(old.l), val(write), r(old.r) {}
TapeTape21b228a86fSRichard Smith constexpr Tape(const Tape &old, Dir dir) :
22b228a86fSRichard Smith l(dir == L ? old.l ? old.l->l : 0 : &old),
23b228a86fSRichard Smith val(dir == L ? old.l ? old.l->val : false
24b228a86fSRichard Smith : old.r ? old.r->val : false),
25b228a86fSRichard Smith r(dir == R ? old.r ? old.r->r : 0 : &old) {}
26b228a86fSRichard Smith const Tape *l;
27b228a86fSRichard Smith bool val;
28b228a86fSRichard Smith const Tape *r;
29b228a86fSRichard Smith };
update(const Tape & old,bool write)30b228a86fSRichard Smith constexpr Tape update(const Tape &old, bool write) { return Tape(old, write); }
move(const Tape & old,Dir dir)31b228a86fSRichard Smith constexpr Tape move(const Tape &old, Dir dir) { return Tape(old, dir); }
32b228a86fSRichard Smith
33b228a86fSRichard Smith // Run turing machine 'tm' on tape 'tape' from state 'state'. Return number of
34b228a86fSRichard Smith // steps taken until halt.
run(const State * tm,const Tape & tape,unsigned state)35b228a86fSRichard Smith constexpr unsigned run(const State *tm, const Tape &tape, unsigned state) {
36*a3ee78dfSRichard Smith return state == halt ? 0 :
37b228a86fSRichard Smith run(tm, move(update(tape, tm[state][tape.val].tape),
38b228a86fSRichard Smith tm[state][tape.val].dir),
39b228a86fSRichard Smith tm[state][tape.val].next) + 1;
40b228a86fSRichard Smith }
41b228a86fSRichard Smith
42*a3ee78dfSRichard Smith // 3-state busy beaver. S(bb3) = 21.
43b228a86fSRichard Smith constexpr State bb3[] = {
44*a3ee78dfSRichard Smith { { true, R, 1 }, { true, R, halt } },
45*a3ee78dfSRichard Smith { { true, L, 1 }, { false, R, 2 } },
46*a3ee78dfSRichard Smith { { true, L, 2 }, { true, L, 0 } }
47b228a86fSRichard Smith };
48*a3ee78dfSRichard Smith static_assert(run(bb3, Tape(), 0) == 21, "");
49b228a86fSRichard Smith
50*a3ee78dfSRichard Smith // 4-state busy beaver. S(bb4) = 107.
51b228a86fSRichard Smith constexpr State bb4[] = {
52b228a86fSRichard Smith { { true, R, 1 }, { true, L, 1 } },
53b228a86fSRichard Smith { { true, L, 0 }, { false, L, 2 } },
54b228a86fSRichard Smith { { true, R, halt }, { true, L, 3 } },
55b228a86fSRichard Smith { { true, R, 3 }, { false, R, 0 } } };
56*a3ee78dfSRichard Smith static_assert(run(bb4, Tape(), 0) == 107, "");
57