197 lines · cpp
1// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s2// RUN: %clang_cc1 -verify=ref,both %s3 4 5constexpr int a = 10;6constexpr const int &b = a;7static_assert(a == b, "");8 9constexpr int assignToReference() {10 int a = 20;11 int &b = a;12 13 b = 100;14 return a;15}16static_assert(assignToReference() == 100, "");17 18 19constexpr void setValue(int &dest, int val) {20 dest = val;21}22 23constexpr int checkSetValue() {24 int l = 100;25 setValue(l, 200);26 return l;27}28static_assert(checkSetValue() == 200, "");29 30constexpr int readLocalRef() {31 int a = 20;32 int &b = a;33 return b;34}35static_assert(readLocalRef() == 20, "");36 37constexpr int incRef() {38 int a = 0;39 int &b = a;40 41 b = b + 1;42 43 return a;44}45static_assert(incRef() == 1, "");46 47 48template<const int &V>49constexpr void Plus3(int &A) {50 A = V + 3;51}52constexpr int foo = 4;53 54constexpr int callTemplate() {55 int a = 3;56 Plus3<foo>(a);57 return a;58}59static_assert(callTemplate() == 7, "");60 61 62constexpr int& getValue(int *array, int index) {63 return array[index];64}65constexpr int testGetValue() {66 int values[] = {1, 2, 3, 4};67 getValue(values, 2) = 30;68 return values[2];69}70static_assert(testGetValue() == 30, "");71 72constexpr const int &MCE = 20;73static_assert(MCE == 20, "");74static_assert(MCE == 30, ""); // both-error {{static assertion failed}} \75 // both-note {{evaluates to '20 == 30'}}76 77constexpr int LocalMCE() {78 const int &m = 100;79 return m;80}81static_assert(LocalMCE() == 100, "");82static_assert(LocalMCE() == 200, ""); // both-error {{static assertion failed}} \83 // both-note {{evaluates to '100 == 200'}}84 85struct S {86 int i, j;87};88 89constexpr int RefToMemberExpr() {90 S s{1, 2};91 92 int &j = s.i;93 j = j + 10;94 95 return j;96}97static_assert(RefToMemberExpr() == 11, "");98 99struct Ref {100 int &a;101};102 103constexpr int RecordWithRef() {104 int m = 100;105 Ref r{m};106 m = 200;107 return r.a;108}109static_assert(RecordWithRef() == 200, "");110 111 112struct Ref2 {113 int &a;114 constexpr Ref2(int &a) : a(a) {}115};116 117constexpr int RecordWithRef2() {118 int m = 100;119 Ref2 r(m);120 m = 200;121 return r.a;122}123static_assert(RecordWithRef2() == 200, "");124 125const char (&nonextended_string_ref)[3] = {"hi"};126static_assert(nonextended_string_ref[0] == 'h', "");127static_assert(nonextended_string_ref[1] == 'i', "");128static_assert(nonextended_string_ref[2] == '\0', "");129 130/// This isa non-constant context. Reading A is not allowed,131/// but taking its address is.132int &&A = 12;133int arr[!&A];134 135namespace 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 144namespace Params {145 typedef __SIZE_TYPE__ size_t;146 147 template <class _Tp, size_t _Np>148 constexpr _Tp* end(_Tp (&__array)[_Np]) noexcept {149 return __array + _Np;150 }151 152 153 struct classnames {154 const char* elem_;155 int a;156 };157 158 constexpr classnames ClassNames[] = {159 {"a", 0},160 {"b", 1},161 {"b", 1},162 {"b", 1},163 {"b", 1},164 {"b", 1},165 {"b", 1},166 {"b", 1},167 };168 169 constexpr bool foo() {170 /// This will instantiate end() with ClassNames.171 /// In Sema, we will constant-evaluate the return statement, which is172 /// something like __array + 8. The APValue we return for this173 /// may NOT have a LValuePath set, since it's for a parameter174 /// of LValueReferenceType.175 end(ClassNames);176 return true;177 }178 179 static_assert(foo());180}181 182namespace ReadFromNullBlockPtr {183 struct S {184 int *const &t;185 };186 187 void foo(int x) {188 constexpr S s = {&x}; // both-error {{must be initialized by a constant expression}} \189 // both-note {{reference to temporary}} \190 // both-note {{created here}} \191 // ref-note {{declared here}}192 static_assert(s.t == &x, ""); // both-error {{not an integral constant expression}} \193 // expected-note {{read of dereferenced null pointer}} \194 // ref-note {{initializer of 's' is not a constant expression}}195 }196}197