xref: /llvm-project/clang/test/AST/ByteCode/references.cpp (revision f79722b932ce40edf2937f3b9386e6fb43757bce)
1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
2 // RUN: %clang_cc1 -verify=ref,both %s
3 
4 
5 constexpr int a = 10;
6 constexpr const int &b = a;
7 static_assert(a == b, "");
8 
9 constexpr int assignToReference() {
10   int a = 20;
11   int &b = a;
12 
13   b = 100;
14   return a;
15 }
16 static_assert(assignToReference() == 100, "");
17 
18 
19 constexpr void setValue(int &dest, int val) {
20   dest = val;
21 }
22 
23 constexpr int checkSetValue() {
24   int l = 100;
25   setValue(l, 200);
26   return l;
27 }
28 static_assert(checkSetValue() == 200, "");
29 
30 constexpr int readLocalRef() {
31   int a = 20;
32   int &b = a;
33   return b;
34 }
35 static_assert(readLocalRef() == 20, "");
36 
37 constexpr int incRef() {
38   int a = 0;
39   int &b = a;
40 
41   b = b + 1;
42 
43   return a;
44 }
45 static_assert(incRef() == 1, "");
46 
47 
48 template<const int &V>
49 constexpr void Plus3(int &A) {
50   A = V + 3;
51 }
52 constexpr int foo = 4;
53 
54 constexpr int callTemplate() {
55   int a = 3;
56   Plus3<foo>(a);
57   return a;
58 }
59 static_assert(callTemplate() == 7, "");
60 
61 
62 constexpr int& getValue(int *array, int index) {
63   return array[index];
64 }
65 constexpr int testGetValue() {
66   int values[] = {1, 2, 3, 4};
67   getValue(values, 2) = 30;
68   return values[2];
69 }
70 static_assert(testGetValue() == 30, "");
71 
72 constexpr const int &MCE = 20;
73 static_assert(MCE == 20, "");
74 static_assert(MCE == 30, ""); // both-error {{static assertion failed}} \
75                               // both-note {{evaluates to '20 == 30'}}
76 
77 constexpr int LocalMCE() {
78   const int &m = 100;
79   return m;
80 }
81 static_assert(LocalMCE() == 100, "");
82 static_assert(LocalMCE() == 200, ""); // both-error {{static assertion failed}} \
83                                       // both-note {{evaluates to '100 == 200'}}
84 
85 struct S {
86   int i, j;
87 };
88 
89 constexpr int RefToMemberExpr() {
90   S s{1, 2};
91 
92   int &j = s.i;
93   j = j + 10;
94 
95   return j;
96 }
97 static_assert(RefToMemberExpr() == 11, "");
98 
99 struct Ref {
100   int &a;
101 };
102 
103 constexpr int RecordWithRef() {
104   int m = 100;
105   Ref r{m};
106   m = 200;
107   return r.a;
108 }
109 static_assert(RecordWithRef() == 200, "");
110 
111 
112 struct Ref2 {
113   int &a;
114   constexpr Ref2(int &a) : a(a) {}
115 };
116 
117 constexpr int RecordWithRef2() {
118   int m = 100;
119   Ref2 r(m);
120   m = 200;
121   return r.a;
122 }
123 static_assert(RecordWithRef2() == 200, "");
124 
125 const char (&nonextended_string_ref)[3] = {"hi"};
126 static_assert(nonextended_string_ref[0] == 'h', "");
127 static_assert(nonextended_string_ref[1] == 'i', "");
128 static_assert(nonextended_string_ref[2] == '\0', "");
129 
130 /// This isa non-constant context. Reading A is not allowed,
131 /// but taking its address is.
132 int &&A = 12;
133 int arr[!&A];
134 
135 namespace Temporaries {
136   struct A { int n; };
137   struct B { const A &a; };
138   const B j = {{1}}; // both-note {{temporary created here}}
139 
140   static_assert(j.a.n == 1, "");  // both-error {{not an integral constant expression}} \
141                                   // both-note {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}}
142 }
143