Richard Smith | 864711ee | 2011-12-16 21:59:02 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -std=c++11 -pedantic -verify -fcxx-exceptions %s -fconstexpr-depth 128 |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2 | |
| 3 | // A conditional-expression is a core constant expression unless it involves one |
| 4 | // of the following as a potentially evaluated subexpression [...]: |
| 5 | |
| 6 | // - this (5.1.1 [expr.prim.general]) [Note: when evaluating a constant |
| 7 | // expression, function invocation substitution (7.1.5 [dcl.constexpr]) |
| 8 | // replaces each occurrence of this in a constexpr member function with a |
| 9 | // pointer to the class object. -end note]; |
| 10 | struct This { |
| 11 | int this1 : this1; // expected-error {{undeclared}} |
| 12 | int this2 : this->this1; // expected-error {{invalid}} |
| 13 | void this3() { |
| 14 | int n1[this->this1]; // expected-warning {{variable length array}} |
| 15 | int n2[this1]; // expected-warning {{variable length array}} |
| 16 | (void)n1, (void)n2; |
| 17 | } |
| 18 | }; |
| 19 | |
| 20 | // - an invocation of a function other than a constexpr constructor for a |
| 21 | // literal class or a constexpr function [ Note: Overload resolution (13.3) |
| 22 | // is applied as usual - end note ]; |
| 23 | struct NonConstexpr1 { |
| 24 | static int f() { return 1; } // expected-note {{here}} |
| 25 | int n : f(); // expected-error {{constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} |
| 26 | }; |
| 27 | struct NonConstexpr2 { |
| 28 | constexpr NonConstexpr2(); // expected-note {{here}} |
| 29 | int n; |
| 30 | }; |
| 31 | struct NonConstexpr3 { |
| 32 | NonConstexpr3(); |
| 33 | int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}} |
| 34 | }; |
| 35 | struct NonConstexpr4 { |
Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame^] | 36 | NonConstexpr4(); // expected-note {{declared here}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 37 | int n; |
| 38 | }; |
| 39 | struct NonConstexpr5 { |
Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame^] | 40 | int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 41 | }; |
| 42 | |
| 43 | // - an invocation of an undefined constexpr function or an undefined |
| 44 | // constexpr constructor; |
| 45 | struct UndefinedConstexpr { |
| 46 | constexpr UndefinedConstexpr(); |
| 47 | static constexpr int undefinedConstexpr1(); // expected-note {{here}} |
| 48 | int undefinedConstexpr2 : undefinedConstexpr1(); // expected-error {{constant expression}} expected-note {{undefined function 'undefinedConstexpr1' cannot be used in a constant expression}} |
| 49 | }; |
| 50 | |
| 51 | // - an invocation of a constexpr function with arguments that, when substituted |
| 52 | // by function invocation substitution (7.1.5), do not produce a constant |
| 53 | // expression; |
| 54 | namespace NonConstExprReturn { |
| 55 | static constexpr const int &id_ref(const int &n) { |
| 56 | return n; // expected-note {{reference to temporary cannot be returned from a constexpr function}} |
| 57 | } |
| 58 | struct NonConstExprFunction { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 59 | int n : id_ref( // expected-error {{constant expression}} expected-note {{in call to 'id_ref(16)'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 60 | 16 // expected-note {{temporary created here}} |
| 61 | ); |
| 62 | }; |
| 63 | constexpr const int *address_of(const int &a) { |
| 64 | return &a; // expected-note {{pointer to 'n' cannot be returned from a constexpr function}} |
| 65 | } |
| 66 | constexpr const int *return_param(int n) { // expected-note {{declared here}} |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 67 | return address_of(n); // expected-note {{in call to 'address_of(n)'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 68 | } |
| 69 | struct S { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 70 | int n : *return_param(0); // expected-error {{constant expression}} expected-note {{in call to 'return_param(0)'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 71 | }; |
| 72 | } |
| 73 | |
| 74 | // - an invocation of a constexpr constructor with arguments that, when |
| 75 | // substituted by function invocation substitution (7.1.5), do not produce all |
| 76 | // constant expressions for the constructor calls and full-expressions in the |
| 77 | // mem-initializers (including conversions); |
| 78 | namespace NonConstExprCtor { |
| 79 | struct T { |
| 80 | constexpr T(const int &r) : |
Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 81 | r(r) { // expected-note 2{{reference to temporary cannot be used to initialize a member in a constant expression}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 82 | } |
| 83 | const int &r; |
| 84 | }; |
| 85 | constexpr int n = 0; |
| 86 | constexpr T t1(n); // ok |
Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 87 | constexpr T t2(0); // expected-error {{must be initialized by a constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'T(0)'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 88 | |
| 89 | struct S { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 90 | int n : T(4).r; // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'T(4)'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 91 | }; |
| 92 | } |
| 93 | |
| 94 | // - an invocation of a constexpr function or a constexpr constructor that would |
| 95 | // exceed the implementation-defined recursion limits (see Annex B); |
| 96 | namespace RecursionLimits { |
| 97 | constexpr int RecurseForever(int n) { |
Richard Smith | 864711ee | 2011-12-16 21:59:02 +0000 | [diff] [blame] | 98 | return n + RecurseForever(n+1); // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'RecurseForever(}} expected-note {{skipping 118 calls}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 99 | } |
| 100 | struct AlsoRecurseForever { |
| 101 | constexpr AlsoRecurseForever(int n) : |
Richard Smith | 864711ee | 2011-12-16 21:59:02 +0000 | [diff] [blame] | 102 | n(AlsoRecurseForever(n+1).n) // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'AlsoRecurseForever(}} expected-note {{skipping 118 calls}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 103 | {} |
| 104 | int n; |
| 105 | }; |
| 106 | struct S { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 107 | int k : RecurseForever(0); // expected-error {{constant expression}} expected-note {{in call to}} |
| 108 | int l : AlsoRecurseForever(0).n; // expected-error {{constant expression}} expected-note {{in call to}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 109 | }; |
| 110 | } |
| 111 | |
| 112 | // FIXME: |
| 113 | // - an operation that would have undefined behavior [Note: including, for |
| 114 | // example, signed integer overflow (Clause 5 [expr]), certain pointer |
| 115 | // arithmetic (5.7 [expr.add]), division by zero (5.6 [expr.mul]), or certain |
| 116 | // shift operations (5.8 [expr.shift]) -end note]; |
| 117 | namespace UndefinedBehavior { |
| 118 | void f(int n) { |
| 119 | switch (n) { |
| 120 | case (int)4.4e9: // expected-error {{constant expression}} expected-note {{value 4.4E+9 is outside the range of representable values of type 'int'}} |
| 121 | case (int)(unsigned)(long long)4.4e9: // ok |
| 122 | case (float)1e300: // expected-error {{constant expression}} expected-note {{value 1.0E+300 is outside the range of representable values of type 'float'}} |
| 123 | case (int)((float)1e37 / 1e30): // ok |
| 124 | case (int)(__fp16)65536: // expected-error {{constant expression}} expected-note {{value 65536 is outside the range of representable values of type 'half'}} |
| 125 | break; |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | struct S { |
| 130 | int m; |
| 131 | }; |
| 132 | constexpr S s = { 5 }; // expected-note {{declared here}} |
| 133 | constexpr const int *p = &s.m + 1; |
| 134 | constexpr const int &f(const int *q) { |
| 135 | return q[0]; // expected-note {{dereferenced pointer past the end of subobject of 's' is not a constant expression}} |
| 136 | } |
| 137 | struct T { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 138 | int n : f(p); // expected-error {{not an integer constant expression}} expected-note {{in call to 'f(&s.m + 1)'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 139 | }; |
| 140 | } |
| 141 | |
| 142 | // - a lambda-expression (5.1.2); |
| 143 | struct Lambda { |
| 144 | // FIXME: clang crashes when trying to parse this! Revisit this check once |
| 145 | // lambdas are fully implemented. |
| 146 | //int n : []{ return 1; }(); |
| 147 | }; |
| 148 | |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 149 | // - an lvalue-to-rvalue conversion (4.1) unless it is applied to |
Richard Smith | f2b681b | 2011-12-21 05:04:46 +0000 | [diff] [blame] | 150 | namespace LValueToRValue { |
| 151 | // - a non-volatile glvalue of integral or enumeration type that refers to a |
| 152 | // non-volatile const object with a preceding initialization, initialized |
| 153 | // with a constant expression [Note: a string literal (2.14.5 [lex.string]) |
| 154 | // corresponds to an array of such objects. -end note], or |
| 155 | volatile const int vi = 1; // expected-note {{here}} |
| 156 | const int ci = 1; |
| 157 | volatile const int &vrci = ci; |
| 158 | static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} |
| 159 | static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} |
| 160 | static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} |
| 161 | |
| 162 | // - a non-volatile glvalue of literal type that refers to a non-volatile |
| 163 | // object defined with constexpr, or that refers to a sub-object of such an |
| 164 | // object, or |
| 165 | struct S { |
| 166 | constexpr S(int=0) : i(1), v(1) {} |
| 167 | constexpr S(const S &s) : i(2), v(2) {} |
| 168 | int i; |
| 169 | volatile int v; |
| 170 | }; |
| 171 | constexpr S s; |
| 172 | constexpr volatile S vs; // expected-note {{here}} |
| 173 | constexpr const volatile S &vrs = s; |
| 174 | static_assert(s.i, ""); |
| 175 | static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} |
| 176 | static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} |
| 177 | static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}} |
| 178 | static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} |
| 179 | |
| 180 | // - a non-volatile glvalue of literal type that refers to a non-volatile |
| 181 | // temporary object whose lifetime has not ended, initialized with a |
| 182 | // constant expression; |
| 183 | constexpr volatile S f() { return S(); } |
| 184 | static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here! |
| 185 | static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{subexpression}} |
| 186 | } |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 187 | |
| 188 | // FIXME: |
| 189 | // |
Richard Smith | f2b681b | 2011-12-21 05:04:46 +0000 | [diff] [blame] | 190 | // DR1312: The proposed wording for this defect has issues, so we ignore this |
| 191 | // bullet and instead prohibit casts from pointers to cv void (see core-20842 |
| 192 | // and core-20845). |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 193 | // |
| 194 | // - an lvalue-to-rvalue conversion (4.1 [conv.lval]) that is applied to a |
| 195 | // glvalue of type cv1 T that refers to an object of type cv2 U, where T and U |
| 196 | // are neither the same type nor similar types (4.4 [conv.qual]); |
| 197 | |
| 198 | // FIXME: |
| 199 | // - an lvalue-to-rvalue conversion (4.1) that is applied to a glvalue that |
| 200 | // refers to a non-active member of a union or a subobject thereof; |
| 201 | |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 202 | // - an id-expression that refers to a variable or data member of reference type |
| 203 | // unless the reference has a preceding initialization, initialized with a |
| 204 | // constant expression; |
| 205 | namespace References { |
| 206 | const int a = 2; |
| 207 | int &b = *const_cast<int*>(&a); |
Richard Smith | f2b681b | 2011-12-21 05:04:46 +0000 | [diff] [blame] | 208 | int c = 10; // expected-note 2 {{here}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 209 | int &d = c; |
| 210 | constexpr int e = 42; |
| 211 | int &f = const_cast<int&>(e); |
| 212 | extern int &g; |
Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 213 | constexpr int &h(); // expected-note 2{{here}} |
| 214 | int &i = h(); // expected-note {{here}} expected-note {{undefined function 'h' cannot be used in a constant expression}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 215 | constexpr int &j() { return b; } |
| 216 | int &k = j(); |
| 217 | |
| 218 | struct S { |
| 219 | int A : a; |
| 220 | int B : b; |
Richard Smith | f2b681b | 2011-12-21 05:04:46 +0000 | [diff] [blame] | 221 | int C : c; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} |
| 222 | int D : d; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 223 | int D2 : &d - &c + 1; |
| 224 | int E : e / 2; |
| 225 | int F : f - 11; |
| 226 | int G : g; // expected-error {{constant expression}} |
| 227 | int H : h(); // expected-error {{constant expression}} expected-note {{undefined function 'h'}} |
Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 228 | int I : i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 229 | int J : j(); |
| 230 | int K : k; |
| 231 | }; |
| 232 | } |
| 233 | |
| 234 | // - a dynamic_cast (5.2.7); |
| 235 | namespace DynamicCast { |
| 236 | struct S { int n; }; |
| 237 | constexpr S s { 16 }; |
| 238 | struct T { |
| 239 | int n : dynamic_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{dynamic_cast}} |
| 240 | }; |
| 241 | } |
| 242 | |
| 243 | // - a reinterpret_cast (5.2.10); |
| 244 | namespace ReinterpretCast { |
| 245 | struct S { int n; }; |
| 246 | constexpr S s { 16 }; |
| 247 | struct T { |
| 248 | int n : reinterpret_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} |
| 249 | }; |
| 250 | struct U { |
| 251 | int m : (long)(S*)6; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} |
| 252 | }; |
| 253 | } |
| 254 | |
| 255 | // - a pseudo-destructor call (5.2.4); |
| 256 | namespace PseudoDtor { |
| 257 | int k; |
| 258 | typedef int I; |
| 259 | struct T { |
| 260 | int n : (k.~I(), 0); // expected-error {{constant expression}} expected-note{{subexpression}} |
| 261 | }; |
| 262 | } |
| 263 | |
| 264 | // - increment or decrement operations (5.2.6, 5.3.2); |
| 265 | namespace IncDec { |
| 266 | int k = 2; |
| 267 | struct T { |
| 268 | int n : ++k; // expected-error {{constant expression}} |
| 269 | int m : --k; // expected-error {{constant expression}} |
| 270 | }; |
| 271 | } |
| 272 | |
| 273 | // - a typeid expression (5.2.8) whose operand is of a polymorphic class type; |
| 274 | namespace std { |
| 275 | struct type_info { |
| 276 | virtual ~type_info(); |
| 277 | const char *name; |
| 278 | }; |
| 279 | } |
| 280 | namespace TypeId { |
| 281 | struct S { virtual void f(); }; |
| 282 | constexpr S *p = 0; |
Richard Smith | 6e52514 | 2011-12-27 12:18:28 +0000 | [diff] [blame] | 283 | constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} expected-note {{typeid applied to expression of polymorphic type 'TypeId::S'}} |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 284 | |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 285 | struct T {} t; |
Richard Smith | 6e52514 | 2011-12-27 12:18:28 +0000 | [diff] [blame] | 286 | constexpr const std::type_info &ti2 = typeid(t); |
Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 287 | } |
| 288 | |
| 289 | // - a new-expression (5.3.4); |
| 290 | // - a delete-expression (5.3.5); |
| 291 | namespace NewDelete { |
| 292 | int *p = 0; |
| 293 | struct T { |
| 294 | int n : *new int(4); // expected-error {{constant expression}} expected-note {{subexpression}} |
| 295 | int m : (delete p, 2); // expected-error {{constant expression}} expected-note {{subexpression}} |
| 296 | }; |
| 297 | } |
| 298 | |
| 299 | // - a relational (5.9) or equality (5.10) operator where the result is |
| 300 | // unspecified; |
| 301 | namespace UnspecifiedRelations { |
| 302 | int a, b; |
| 303 | constexpr int *p = &a, *q = &b; |
| 304 | // C++11 [expr.rel]p2: If two pointers p and q of the same type point to |
| 305 | // different objects that are not members of the same array or to different |
| 306 | // functions, or if only one of them is null, the results of p<q, p>q, p<=q, |
| 307 | // and p>=q are unspecified. |
| 308 | constexpr bool u1 = p < q; // expected-error {{constant expression}} |
| 309 | constexpr bool u2 = p > q; // expected-error {{constant expression}} |
| 310 | constexpr bool u3 = p <= q; // expected-error {{constant expression}} |
| 311 | constexpr bool u4 = p >= q; // expected-error {{constant expression}} |
| 312 | constexpr bool u5 = p < 0; // expected-error {{constant expression}} |
| 313 | constexpr bool u6 = p <= 0; // expected-error {{constant expression}} |
| 314 | constexpr bool u7 = p > 0; // expected-error {{constant expression}} |
| 315 | constexpr bool u8 = p >= 0; // expected-error {{constant expression}} |
| 316 | constexpr bool u9 = 0 < q; // expected-error {{constant expression}} |
| 317 | constexpr bool u10 = 0 <= q; // expected-error {{constant expression}} |
| 318 | constexpr bool u11 = 0 > q; // expected-error {{constant expression}} |
| 319 | constexpr bool u12 = 0 >= q; // expected-error {{constant expression}} |
| 320 | void f(), g(); |
| 321 | |
| 322 | constexpr void (*pf)() = &f, (*pg)() = &g; |
| 323 | constexpr bool u13 = pf < pg; // expected-error {{constant expression}} |
| 324 | constexpr bool u14 = pf == pg; |
| 325 | |
| 326 | // FIXME: |
| 327 | // If two pointers point to non-static data members of the same object with |
| 328 | // different access control, the result is unspecified. |
| 329 | |
| 330 | // FIXME: |
| 331 | // [expr.rel]p3: Pointers to void can be compared [...] if both pointers |
| 332 | // represent the same address or are both the null pointer [...]; otherwise |
| 333 | // the result is unspecified. |
| 334 | |
| 335 | // FIXME: Implement comparisons of pointers to members. |
| 336 | // [expr.eq]p2: If either is a pointer to a virtual member function and |
| 337 | // neither is null, the result is unspecified. |
| 338 | } |
| 339 | |
| 340 | // - an assignment or a compound assignment (5.17); or |
| 341 | namespace Assignment { |
| 342 | int k; |
| 343 | struct T { |
| 344 | int n : (k = 9); // expected-error {{constant expression}} |
| 345 | int m : (k *= 2); // expected-error {{constant expression}} |
| 346 | }; |
| 347 | |
| 348 | struct Literal { |
| 349 | constexpr Literal(const char *name) : name(name) {} |
| 350 | const char *name; |
| 351 | }; |
| 352 | struct Expr { |
| 353 | constexpr Expr(Literal l) : IsLiteral(true), l(l) {} |
| 354 | bool IsLiteral; |
| 355 | union { |
| 356 | Literal l; |
| 357 | // ... |
| 358 | }; |
| 359 | }; |
| 360 | struct MulEq { |
| 361 | constexpr MulEq(Expr a, Expr b) : LHS(a), RHS(b) {} |
| 362 | Expr LHS; |
| 363 | Expr RHS; |
| 364 | }; |
| 365 | constexpr MulEq operator*=(Expr a, Expr b) { return MulEq(a, b); } |
| 366 | Literal a("a"); |
| 367 | Literal b("b"); |
| 368 | MulEq c = a *= b; // ok |
| 369 | } |
| 370 | |
| 371 | // - a throw-expression (15.1) |
| 372 | namespace Throw { |
| 373 | struct S { |
| 374 | int n : (throw "hello", 10); // expected-error {{constant expression}} expected-note {{subexpression}} |
| 375 | }; |
| 376 | } |
Douglas Gregor | fcafc6e | 2011-05-24 16:02:01 +0000 | [diff] [blame] | 377 | |
| 378 | // PR9999 |
| 379 | template<bool v> |
| 380 | class bitWidthHolding { |
| 381 | public: |
| 382 | static const |
| 383 | unsigned int width = (v == 0 ? 0 : bitWidthHolding<(v >> 1)>::width + 1); |
| 384 | }; |
| 385 | |
| 386 | static const int width=bitWidthHolding<255>::width; |
| 387 | |
| 388 | template<bool b> |
| 389 | struct always_false { |
| 390 | static const bool value = false; |
| 391 | }; |
| 392 | |
| 393 | template<bool b> |
| 394 | struct and_or { |
| 395 | static const bool and_value = b && and_or<always_false<b>::value>::and_value; |
| 396 | static const bool or_value = !b || and_or<always_false<b>::value>::or_value; |
| 397 | }; |
| 398 | |
| 399 | static const bool and_value = and_or<true>::and_value; |
| 400 | static const bool or_value = and_or<true>::or_value; |