constant-expression-cxx11.cpp revision f64699e8db3946e21b5f4a0421cbc58a3e439599
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RUN: %clang_cc1 -triple i686-linux -fsyntax-only -verify -std=c++11 %s 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This version of static_assert just requires a foldable value as the 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expression, not an ICE. 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// FIXME: Once we implement the C++11 ICE rules, most uses of this here should 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// be converted to static_assert. 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define static_assert_fold(expr, str) \ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert(__builtin_constant_p(expr), "not an integral constant expression"); \ 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static_assert(__builtin_constant_p(expr) ? expr : true, str) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace StaticAssertFoldTest { 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int x; 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static_assert_fold(++x, "test"); // expected-error {{not an integral constant expression}} 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static_assert_fold(false, "test"); // expected-error {{test}} 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FIXME: support const T& parameters here. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//template<typename T> constexpr T id(const T &t) { return t; } 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> constexpr T id(T t) { return t; } 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FIXME: support templates here. 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//template<typename T> constexpr T min(const T &a, const T &b) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return a < b ? a : b; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//template<typename T> constexpr T max(const T &a, const T &b) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return a < b ? b : a; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)constexpr int min(const int &a, const int &b) { return a < b ? a : b; } 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)constexpr int max(const int &a, const int &b) { return a < b ? b : a; } 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct MemberZero { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) constexpr int zero() { return 0; } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace DerivedToVBaseCast { 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct U { int n; }; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct V : U { int n; }; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct A : virtual V { int n; }; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Aa { int n; }; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct B : virtual A, Aa {}; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct C : virtual A, Aa {}; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct D : B, C {}; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) D d; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constexpr B *p = &d; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constexpr C *q = &d; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((void*)p != (void*)q, ""); 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) static_assert_fold((A*)p == (A*)q, ""); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((Aa*)p != (Aa*)q, ""); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) constexpr B &pp = d; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constexpr C &qq = d; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((void*)&pp != (void*)&qq, ""); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold(&(A&)pp == &(A&)qq, ""); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold(&(Aa&)pp != &(Aa&)qq, ""); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constexpr V *v = p; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constexpr V *w = q; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constexpr V *x = (A*)p; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold(v == w, ""); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold(v == x, ""); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((U*)&d == p, ""); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_assert_fold((U*)&d == q, ""); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((U*)&d == v, ""); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((U*)&d == w, ""); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((U*)&d == x, ""); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct X {}; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Y1 : virtual X {}; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Y2 : X {}; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Z : Y1, Y2 {}; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Z z; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_assert_fold((X*)(Y1*)&z != (X*)(Y2*)&z, ""); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ConstCast { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)constexpr int n1 = 0; 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)constexpr int n2 = const_cast<int&>(n1); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constexpr int *n3 = const_cast<int*>(&n1); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constexpr int n4 = *const_cast<int*>(&n1); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constexpr const int * const *n5 = const_cast<const int* const*>(&n3); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constexpr int **n6 = const_cast<int**>(&n3); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constexpr int n7 = **n5; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)constexpr int n8 = **n6; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace TemplateArgumentConversion { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<int n> struct IntParam {}; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) using IntParam0 = IntParam<0>; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: This should be accepted once we do constexpr function invocation. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using IntParam0 = IntParam<id(0)>; // expected-error {{not an integral constant expression}} 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} expected-error {{not an integral constant expression}} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace CaseStatements { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void f(int n) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (n) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // FIXME: Produce the 'add ()' fixit for this. 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MemberZero().zero: // desired-error {{did you mean to call it with no arguments?}} expected-error {{not an integer constant expression}} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: This should be accepted once we do constexpr function invocation. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case id(1): // expected-error {{not an integer constant expression}} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern int &Recurse1; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int &Recurse2 = Recurse1, &Recurse1 = Recurse2; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace MemberEnum { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct WithMemberEnum { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum E { A = 42 }; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } wme; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 123 static_assert_fold(wme.A == 42, ""); 124} 125 126namespace DefaultArguments { 127 128const int z = int(); 129constexpr int Sum(int a = 0, const int &b = 0, const int *c = &z, char d = 0) { 130 return a + b + *c + d; 131} 132const int four = 4; 133constexpr int eight = 8; 134constexpr const int twentyseven = 27; 135static_assert_fold(Sum() == 0, ""); 136static_assert_fold(Sum(1) == 1, ""); 137static_assert_fold(Sum(1, four) == 5, ""); 138static_assert_fold(Sum(1, eight, &twentyseven) == 36, ""); 139static_assert_fold(Sum(1, 2, &four, eight) == 15, ""); 140 141} 142 143namespace Ellipsis { 144 145// Note, values passed through an ellipsis can't actually be used. 146constexpr int F(int a, ...) { return a; } 147static_assert_fold(F(0) == 0, ""); 148static_assert_fold(F(1, 0) == 1, ""); 149static_assert_fold(F(2, "test") == 2, ""); 150static_assert_fold(F(3, &F) == 3, ""); 151int k = 0; 152static_assert_fold(F(4, k) == 3, ""); // expected-error {{constant expression}} 153 154} 155 156namespace Recursion { 157 constexpr int fib(int n) { return n > 1 ? fib(n-1) + fib(n-2) : n; } 158 static_assert_fold(fib(11) == 89, ""); 159 160 constexpr int gcd_inner(int a, int b) { 161 return b == 0 ? a : gcd_inner(b, a % b); 162 } 163 constexpr int gcd(int a, int b) { 164 return gcd_inner(max(a, b), min(a, b)); 165 } 166 167 static_assert_fold(gcd(1749237, 5628959) == 7, ""); 168} 169 170namespace FunctionCast { 171 // When folding, we allow functions to be cast to different types. Such 172 // cast functions cannot be called, even if they're constexpr. 173 constexpr int f() { return 1; } 174 typedef double (*DoubleFn)(); 175 typedef int (*IntFn)(); 176 int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}} 177 int b[(int)IntFn(f)()]; // ok 178} 179 180namespace StaticMemberFunction { 181 struct S { 182 static constexpr int k = 42; 183 static constexpr int f(int n) { return n * k + 2; } 184 } s; 185 186 constexpr int n = s.f(19); 187 static_assert_fold(S::f(19) == 800, ""); 188 static_assert_fold(s.f(19) == 800, ""); 189 static_assert_fold(n == 800, ""); 190} 191 192namespace ParameterScopes { 193 194 const int k = 42; 195 constexpr const int &ObscureTheTruth(const int &a) { return a; } 196 constexpr const int &MaybeReturnJunk(bool b, const int a) { 197 return ObscureTheTruth(b ? a : k); 198 } 199 static_assert_fold(MaybeReturnJunk(false, 0) == 42, ""); // ok 200 constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} 201 202 constexpr const int MaybeReturnNonstaticRef(bool b, const int a) { 203 // If ObscureTheTruth returns a reference to 'a', the result is not a 204 // constant expression even though 'a' is still in scope. 205 return ObscureTheTruth(b ? a : k); 206 } 207 static_assert_fold(MaybeReturnNonstaticRef(false, 0) == 42, ""); // ok 208 constexpr int b = MaybeReturnNonstaticRef(true, 0); // expected-error {{constant expression}} 209 210 constexpr int InternalReturnJunk(int n) { 211 // FIXME: We should reject this: it never produces a constant expression. 212 return MaybeReturnJunk(true, n); 213 } 214 constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}} 215 216 constexpr int LToR(int &n) { return n; } 217 constexpr int GrabCallersArgument(bool which, int a, int b) { 218 return LToR(which ? b : a); 219 } 220 static_assert_fold(GrabCallersArgument(false, 1, 2) == 1, ""); 221 static_assert_fold(GrabCallersArgument(true, 4, 8) == 8, ""); 222 223} 224 225namespace Pointers { 226 227 constexpr int f(int n, const int *a, const int *b, const int *c) { 228 return n == 0 ? 0 : *a + f(n-1, b, c, a); 229 } 230 231 const int x = 1, y = 10, z = 100; 232 static_assert_fold(f(23, &x, &y, &z) == 788, ""); 233 234 constexpr int g(int n, int a, int b, int c) { 235 return f(n, &a, &b, &c); 236 } 237 static_assert_fold(g(23, x, y, z) == 788, ""); 238 239} 240 241namespace FunctionPointers { 242 243 constexpr int Double(int n) { return 2 * n; } 244 constexpr int Triple(int n) { return 3 * n; } 245 constexpr int Twice(int (*F)(int), int n) { return F(F(n)); } 246 constexpr int Quadruple(int n) { return Twice(Double, n); } 247 constexpr auto Select(int n) -> int (*)(int) { 248 return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0; 249 } 250 constexpr int Apply(int (*F)(int), int n) { return F(n); } 251 252 static_assert_fold(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, ""); 253 254 constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} 255 256} 257 258namespace PointerComparison { 259 260int x, y; 261static_assert_fold(&x == &y, "false"); // expected-error {{false}} 262static_assert_fold(&x != &y, ""); 263constexpr bool g1 = &x == &y; 264constexpr bool g2 = &x != &y; 265constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}} 266constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}} 267constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}} 268constexpr bool g6 = &x > &y; // expected-error {{must be initialized by a constant expression}} 269 270struct S { int x, y; } s; 271static_assert_fold(&s.x == &s.y, "false"); // expected-error {{false}} 272static_assert_fold(&s.x != &s.y, ""); 273static_assert_fold(&s.x <= &s.y, ""); 274static_assert_fold(&s.x >= &s.y, "false"); // expected-error {{false}} 275static_assert_fold(&s.x < &s.y, ""); 276static_assert_fold(&s.x > &s.y, "false"); // expected-error {{false}} 277 278static_assert_fold(0 == &y, "false"); // expected-error {{false}} 279static_assert_fold(0 != &y, ""); 280constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}} 281constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}} 282constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}} 283constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}} 284 285static_assert_fold(&x == 0, "false"); // expected-error {{false}} 286static_assert_fold(&x != 0, ""); 287constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}} 288constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}} 289constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}} 290constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}} 291 292static_assert_fold(&x == &x, ""); 293static_assert_fold(&x != &x, "false"); // expected-error {{false}} 294static_assert_fold(&x <= &x, ""); 295static_assert_fold(&x >= &x, ""); 296static_assert_fold(&x < &x, "false"); // expected-error {{false}} 297static_assert_fold(&x > &x, "false"); // expected-error {{false}} 298 299constexpr S* sptr = &s; 300// FIXME: This is not a constant expression; check we reject this and move this 301// test elsewhere. 302constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr); 303 304extern char externalvar[]; 305// FIXME: This is not a constant expression; check we reject this and move this 306// test elsewhere. 307constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; // expected-error {{must be initialized by a constant expression}} 308constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}} expected-warning {{unspecified}} 309static_assert_fold(0 != "foo", ""); 310 311} 312 313namespace MaterializeTemporary { 314 315constexpr int f(const int &r) { return r; } 316constexpr int n = f(1); 317 318constexpr bool same(const int &a, const int &b) { return &a == &b; } 319constexpr bool sameTemporary(const int &n) { return same(n, n); } 320 321static_assert_fold(n, ""); 322static_assert_fold(!same(4, 4), ""); 323static_assert_fold(same(n, n), ""); 324static_assert_fold(sameTemporary(9), ""); 325 326} 327 328constexpr int strcmp_ce(const char *p, const char *q) { 329 return (!*p || *p != *q) ? *p - *q : strcmp_ce(p+1, q+1); 330} 331 332namespace StringLiteral { 333 334// FIXME: Refactor this once we support constexpr templates. 335constexpr int MangleChars(const char *p) { 336 return *p + 3 * (*p ? MangleChars(p+1) : 0); 337} 338constexpr int MangleChars(const char16_t *p) { 339 return *p + 3 * (*p ? MangleChars(p+1) : 0); 340} 341constexpr int MangleChars(const char32_t *p) { 342 return *p + 3 * (*p ? MangleChars(p+1) : 0); 343} 344 345static_assert_fold(MangleChars("constexpr!") == 1768383, ""); 346static_assert_fold(MangleChars(u"constexpr!") == 1768383, ""); 347static_assert_fold(MangleChars(U"constexpr!") == 1768383, ""); 348 349constexpr char c0 = "nought index"[0]; 350constexpr char c1 = "nice index"[10]; 351constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{indexes past the end}} 352constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{indexes before the beginning}} 353constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} 354 355constexpr const char *p = "test" + 2; 356static_assert_fold(*p == 's', ""); 357 358constexpr const char *max_iter(const char *a, const char *b) { 359 return *a < *b ? b : a; 360} 361constexpr const char *max_element(const char *a, const char *b) { 362 return (a+1 >= b) ? a : max_iter(a, max_element(a+1, b)); 363} 364 365constexpr const char *begin(const char (&arr)[45]) { return arr; } 366constexpr const char *end(const char (&arr)[45]) { return arr + 45; } 367 368constexpr char str[] = "the quick brown fox jumped over the lazy dog"; 369constexpr const char *max = max_element(begin(str), end(str)); 370static_assert_fold(*max == 'z', ""); 371static_assert_fold(max == str + 38, ""); 372 373static_assert_fold(strcmp_ce("hello world", "hello world") == 0, ""); 374static_assert_fold(strcmp_ce("hello world", "hello clang") > 0, ""); 375static_assert_fold(strcmp_ce("constexpr", "test") < 0, ""); 376static_assert_fold(strcmp_ce("", " ") < 0, ""); 377 378} 379 380namespace Array { 381 382// FIXME: Use templates for these once we support constexpr templates. 383constexpr int Sum(const int *begin, const int *end) { 384 return begin == end ? 0 : *begin + Sum(begin+1, end); 385} 386constexpr const int *begin(const int (&xs)[5]) { return xs; } 387constexpr const int *end(const int (&xs)[5]) { return xs + 5; } 388 389constexpr int xs[] = { 1, 2, 3, 4, 5 }; 390constexpr int ys[] = { 5, 4, 3, 2, 1 }; 391constexpr int sum_xs = Sum(begin(xs), end(xs)); 392static_assert_fold(sum_xs == 15, ""); 393 394constexpr int ZipFoldR(int (*F)(int x, int y, int c), int n, 395 const int *xs, const int *ys, int c) { 396 return n ? F(*xs, *ys, ZipFoldR(F, n-1, xs+1, ys+1, c)) : c; 397} 398constexpr int MulAdd(int x, int y, int c) { return x * y + c; } 399constexpr int InnerProduct = ZipFoldR(MulAdd, 5, xs, ys, 0); 400static_assert_fold(InnerProduct == 35, ""); 401 402constexpr int SubMul(int x, int y, int c) { return (x - y) * c; } 403constexpr int DiffProd = ZipFoldR(SubMul, 2, xs+3, ys+3, 1); 404static_assert_fold(DiffProd == 8, ""); 405static_assert_fold(ZipFoldR(SubMul, 3, xs+3, ys+3, 1), ""); // expected-error {{constant expression}} 406 407constexpr const int *p = xs + 3; 408constexpr int xs4 = p[1]; // ok 409constexpr int xs5 = p[2]; // expected-error {{constant expression}} 410constexpr int xs0 = p[-3]; // ok 411constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} 412 413constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 414static_assert_fold(zs[0][0][0][0] == 1, ""); 415static_assert_fold(zs[1][1][1][1] == 16, ""); 416static_assert_fold(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} 417static_assert_fold((&zs[0][0][0][2])[-1] == 2, ""); 418static_assert_fold(**(**(zs + 1) + 1) == 11, ""); 419static_assert_fold(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, ""); 420 421constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; 422constexpr int SumNonzero(const int *p) { 423 return *p + (*p ? SumNonzero(p+1) : 0); 424} 425constexpr int CountZero(const int *p, const int *q) { 426 return p == q ? 0 : (*p == 0) + CountZero(p+1, q); 427} 428static_assert_fold(SumNonzero(arr) == 6, ""); 429static_assert_fold(CountZero(arr, arr + 40) == 36, ""); 430 431} 432 433namespace DependentValues { 434 435struct I { int n; typedef I V[10]; }; 436I::V x, y; 437template<bool B> struct S { 438 int k; 439 void f() { 440 I::V &cells = B ? x : y; 441 I &i = cells[k]; 442 switch (i.n) {} 443 } 444}; 445 446} 447 448namespace Class { 449 450struct A { constexpr A(int a, int b) : k(a + b) {} int k; }; 451constexpr int fn(const A &a) { return a.k; } 452static_assert_fold(fn(A(4,5)) == 9, ""); 453 454struct B { int n; int m; } constexpr b = { 0, b.n }; // expected-warning {{uninitialized}} 455struct C { 456 constexpr C(C *this_) : m(42), n(this_->m) {} // ok 457 int m, n; 458}; 459struct D { 460 C c; 461 constexpr D() : c(&c) {} 462}; 463static_assert_fold(D().c.n == 42, ""); 464 465struct E { 466 constexpr E() : p(&p) {} 467 void *p; 468}; 469constexpr const E &e1 = E(); // expected-error {{constant expression}} 470// This is a constant expression if we elide the copy constructor call, and 471// is not a constant expression if we don't! But we do, so it is. 472// FIXME: The move constructor is not currently implicitly defined as constexpr. 473// We notice this when evaluating an expression which uses it, but not when 474// checking its initializer. 475constexpr E e2 = E(); // unexpected-error {{constant expression}} 476static_assert_fold(e2.p == &e2.p, ""); // unexpected-error {{constant expression}} 477// FIXME: We don't pass through the fact that 'this' is ::e3 when checking the 478// initializer of this declaration. 479constexpr E e3; // unexpected-error {{constant expression}} 480static_assert_fold(e3.p == &e3.p, ""); 481 482extern const class F f; 483struct F { 484 constexpr F() : p(&f.p) {} 485 const void *p; 486}; 487constexpr F f = F(); 488 489struct G { 490 struct T { 491 constexpr T(T *p) : u1(), u2(p) {} 492 union U1 { 493 constexpr U1() {} 494 int a, b = 42; 495 } u1; 496 union U2 { 497 constexpr U2(T *p) : c(p->u1.b) {} 498 int c, d; 499 } u2; 500 } t; 501 constexpr G() : t(&t) {} 502} constexpr g; 503 504static_assert_fold(g.t.u1.a == 42, ""); // expected-error {{constant expression}} 505static_assert_fold(g.t.u1.b == 42, ""); 506static_assert_fold(g.t.u2.c == 42, ""); 507static_assert_fold(g.t.u2.d == 42, ""); // expected-error {{constant expression}} 508 509struct S { 510 int a, b; 511 const S *p; 512 double d; 513 const char *q; 514 515 constexpr S(int n, const S *p) : a(5), b(n), p(p), d(n), q("hello") {} 516}; 517 518S global(43, &global); 519 520static_assert_fold(S(15, &global).b == 15, ""); 521 522constexpr bool CheckS(const S &s) { 523 return s.a == 5 && s.b == 27 && s.p == &global && s.d == 27. && s.q[3] == 'l'; 524} 525static_assert_fold(CheckS(S(27, &global)), ""); 526 527struct Arr { 528 char arr[3]; 529 constexpr Arr() : arr{'x', 'y', 'z'} {} 530}; 531constexpr int hash(Arr &&a) { 532 return a.arr[0] + a.arr[1] * 0x100 + a.arr[2] * 0x10000; 533} 534constexpr int k = hash(Arr()); 535static_assert_fold(k == 0x007a7978, ""); 536 537 538struct AggregateInit { 539 const char &c; 540 int n; 541 double d; 542 int arr[5]; 543 void *p; 544}; 545 546constexpr AggregateInit agg1 = { "hello"[0] }; 547 548static_assert_fold(strcmp_ce(&agg1.c, "hello") == 0, ""); 549static_assert_fold(agg1.n == 0, ""); 550static_assert_fold(agg1.d == 0.0, ""); 551static_assert_fold(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} 552static_assert_fold(agg1.arr[0] == 0, ""); 553static_assert_fold(agg1.arr[4] == 0, ""); 554static_assert_fold(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} 555static_assert_fold(agg1.p == nullptr, ""); 556 557namespace SimpleDerivedClass { 558 559struct B { 560 constexpr B(int n) : a(n) {} 561 int a; 562}; 563struct D : B { 564 constexpr D(int n) : B(n) {} 565}; 566constexpr D d(3); 567static_assert_fold(d.a == 3, ""); 568 569} 570 571struct Base { 572 constexpr Base(int a = 42, const char *b = "test") : a(a), b(b) {} 573 int a; 574 const char *b; 575}; 576struct Base2 { 577 constexpr Base2(const int &r) : r(r) {} 578 int q = 123; 579 // FIXME: When we track the global for which we are computing the initializer, 580 // use a reference here. 581 //const int &r; 582 int r; 583}; 584struct Derived : Base, Base2 { 585 constexpr Derived() : Base(76), Base2(a) {} 586 int c = r + b[1]; 587}; 588 589constexpr bool operator==(const Base &a, const Base &b) { 590 return a.a == b.a && strcmp_ce(a.b, b.b) == 0; 591} 592 593constexpr Base base; 594constexpr Base base2(76); 595constexpr Derived derived; 596static_assert_fold(derived.a == 76, ""); 597static_assert_fold(derived.b[2] == 's', ""); 598static_assert_fold(derived.c == 76 + 'e', ""); 599static_assert_fold(derived.q == 123, ""); 600static_assert_fold(derived.r == 76, ""); 601static_assert_fold(&derived.r == &derived.a, ""); // expected-error {{}} 602 603static_assert_fold(!(derived == base), ""); 604static_assert_fold(derived == base2, ""); 605 606} 607 608namespace Union { 609 610union U { 611 int a; 612 int b; 613}; 614 615constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; 616static_assert_fold(u[0].a == 0, ""); 617static_assert_fold(u[0].b, ""); // expected-error {{constant expression}} 618static_assert_fold(u[1].b == 1, ""); 619static_assert_fold((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}} 620static_assert_fold(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} 621static_assert_fold((&(u[1]) + 1 + 1)->b == 3, ""); 622 623} 624 625namespace Complex { 626 627class complex { 628 int re, im; 629public: 630 constexpr complex(int re = 0, int im = 0) : re(re), im(im) {} 631 constexpr complex(const complex &o) : re(o.re), im(o.im) {} 632 constexpr complex operator-() const { return complex(-re, -im); } 633 friend constexpr complex operator+(const complex &l, const complex &r) { 634 return complex(l.re + r.re, l.im + r.im); 635 } 636 friend constexpr complex operator-(const complex &l, const complex &r) { 637 return l + -r; 638 } 639 friend constexpr complex operator*(const complex &l, const complex &r) { 640 return complex(l.re * r.re - l.im * r.im, l.re * r.im + l.im * r.re); 641 } 642 friend constexpr bool operator==(const complex &l, const complex &r) { 643 return l.re == r.re && l.im == r.im; 644 } 645 constexpr bool operator!=(const complex &r) const { 646 return re != r.re || im != r.im; 647 } 648 constexpr int real() const { return re; } 649 constexpr int imag() const { return im; } 650}; 651 652constexpr complex i = complex(0, 1); 653constexpr complex k = (3 + 4*i) * (6 - 4*i); 654static_assert_fold(complex(1,0).real() == 1, ""); 655static_assert_fold(complex(1,0).imag() == 0, ""); 656static_assert_fold(((complex)1).imag() == 0, ""); 657static_assert_fold(k.real() == 34, ""); 658static_assert_fold(k.imag() == 12, ""); 659static_assert_fold(k - 34 == 12*i, ""); 660static_assert_fold((complex)1 == complex(1), ""); 661static_assert_fold((complex)1 != complex(0, 1), ""); 662static_assert_fold(complex(1) == complex(1), ""); 663static_assert_fold(complex(1) != complex(0, 1), ""); 664constexpr complex makeComplex(int re, int im) { return complex(re, im); } 665static_assert_fold(makeComplex(1,0) == complex(1), ""); 666static_assert_fold(makeComplex(1,0) != complex(0, 1), ""); 667 668class complex_wrap : public complex { 669public: 670 constexpr complex_wrap(int re, int im = 0) : complex(re, im) {} 671 constexpr complex_wrap(const complex_wrap &o) : complex(o) {} 672}; 673 674static_assert_fold((complex_wrap)1 == complex(1), ""); 675static_assert_fold((complex)1 != complex_wrap(0, 1), ""); 676static_assert_fold(complex(1) == complex_wrap(1), ""); 677static_assert_fold(complex_wrap(1) != complex(0, 1), ""); 678constexpr complex_wrap makeComplexWrap(int re, int im) { 679 return complex_wrap(re, im); 680} 681static_assert_fold(makeComplexWrap(1,0) == complex(1), ""); 682static_assert_fold(makeComplexWrap(1,0) != complex(0, 1), ""); 683 684} 685