xref: /llvm-project/clang/test/AST/ByteCode/constexpr-nqueens.cpp (revision a07aba5d44204a7ca0d891a3da05af9960081e4c)
1 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=ref %s
2 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -fexperimental-new-constant-interpreter -verify %s
3 
4 /// This is a version of the nqueens.cpp from SemaCXX/,
5 /// but we don't initialize the State variable in the
6 /// Board constructors.
7 /// This tests that InterpFrame::describe().
8 
9 typedef unsigned long uint64_t;
10 
11 struct Board {
12   uint64_t State;
13   bool Failed;
14 
15   constexpr Board() : Failed(false) {}
16   constexpr Board(const Board &O) : Failed(O.Failed) {}
17   constexpr Board(uint64_t State, bool Failed = false) :
18     Failed(Failed) {}
19   constexpr Board addQueen(int Row, int Col) const {
20     return Board(State | ((uint64_t)Row << (Col * 4))); // ref-note {{read of uninitialized object}} \
21                                                         // expected-note {{read of uninitialized object}}
22   }
23   constexpr int getQueenRow(int Col) const {
24     return (State >> (Col * 4)) & 0xf;
25   }
26   constexpr bool ok(int Row, int Col) const {
27     return okRecurse(Row, Col, 0);
28   }
29   constexpr bool okRecurse(int Row, int Col, int CheckCol) const {
30     return Col == CheckCol ? true :
31            getQueenRow(CheckCol) == Row ? false :
32            getQueenRow(CheckCol) == Row + (Col - CheckCol) ? false :
33            getQueenRow(CheckCol) == Row + (CheckCol - Col) ? false :
34            okRecurse(Row, Col, CheckCol + 1);
35   }
36   constexpr bool at(int Row, int Col) const {
37     return getQueenRow(Col) == Row;
38   }
39   constexpr bool check(const char *, int=0, int=0) const;
40 };
41 
42 constexpr Board buildBoardRecurse(int N, int Col, const Board &B);
43 constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B);
44 constexpr Board tryBoard(const Board &Try,
45                          int N, int Col, int Row, const Board &B) {
46   return Try.Failed ? buildBoardScan(N, Col, Row, B) : Try;
47 }
48 constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) {
49   return Row == N ? Board(0, true) :
50          B.ok(Row, Col) ?
51          tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), // ref-note {{in call to 'B.addQueen(0, 0)}} \
52                                                                        // expected-note {{in call to 'B.addQueen(0, 0)}}
53                   N, Col, Row+1, B) :
54          buildBoardScan(N, Col, Row + 1, B);
55 }
56 constexpr Board buildBoardRecurse(int N, int Col, const Board &B) {
57   return Col == N ? B : buildBoardScan(N, Col, 0, B); // ref-note {{in call to 'buildBoardScan(8, 0, 0, Board())'}} \
58                                                       // expected-note {{in call to 'buildBoardScan(8, 0, 0, Board())'}}
59 
60 }
61 constexpr Board buildBoard(int N) {
62   return buildBoardRecurse(N, 0, Board()); // ref-note {{in call to 'buildBoardRecurse(8, 0, Board())'}} \
63                                            // expected-note {{in call to 'buildBoardRecurse(8, 0, Board())'}}
64 }
65 
66 constexpr Board q8 = buildBoard(8); // ref-error {{must be initialized by a constant expression}} \
67                                     // ref-note {{in call to 'buildBoard(8)'}} \
68                                     // expected-error {{must be initialized by a constant expression}} \
69                                     // expected-note {{in call to 'buildBoard(8)'}}
70