Hi, When I try to cross-compile 1.3.5 for android, with clang 8.0.7 (same with clang 9.0.0), it generates an intparam.h with: #error "Integers of type int have no binary representation!!" #error "Integers of type long have no binary representation!!" #error "Integers of type long long have no binary representation!!"[...] #error "Integer types int and unsigned int have different sizes!!" #error "Integer types long and unsigned long have different sizes!!" #error "Integer types long long and unsigned long long have different sizes!!" #error "Type char * does not fit into an intptr_t!!" I do not get the same errors with 1.3.4. It seems to due to the typedef int[<negative>] -> static_assert change done in 2f7994014542920ad6ca726fbd8d023a5f49abc2. Reverting that commit makes the build succeed again. If I compile the old type of test, everything works fine, so int main() { typedef int verify[2*((int)((int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2) == 0) - 1]; ; return 0; } compiles without errors, while the same test with static_assert int main() { static_assert((int)((int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2 * (int)2) == 0, ""); ; return 0; } fails with "test_new.cpp:3:17: error: static_assert expression is not an integral constant expression" I unfortunately do not know what the proper fix would be, but reverting 2f7994014542920ad6ca726fbd8d023a5f49abc2 makes the build succeed again at least. Best regards, Henrik Grimler
Hi, It's good hearing from you again, Alexey! On 12/4/19 6:19 PM, Alexey Sheplyakov wrote:
This code relies on integer multiplication overflow to find out the bit size of various integer types. However singed integer overflow is an undefined behavior. Apparently in some contexts GCC uses mod 2^N arithmetics to evaluate the signed integer expressions. As a result `typedef int[2*((T)((T)2 * ... * (T)2) == 0) - 1]` trick works with both signed and unsigned integers (and gives the correct result). Howerver GCC considers an expression involving an integer overflow as a non-constant, and refuses to use it in `static_assert`
Right. According to section 5.19 in the C++11 standard (but the equivalent section 8.20 in C++17 is much more clear), an "integral constant" is implicitly converted to a prvalue where the converted expression is a "core constant". And by the same standard sections it's not a "core constant" if it has undefined behavior like signed integer overflow. I guess that explains why static_assert doesn't work here. But I find it interesting that the C++ requirements on "integral constants" / "core constants" do not seem to apply to the "condition" in typedef int[2*(condition) - 1] trick. I'm unsure if this is really compliant. Anyway, I've applied your patch. All my best, -richy. -- Richard B. Kreckel <https://in.terlu.de/~kreckel/>
participants (3)
-
Alexey Sheplyakov
-
Henrik Grimler
-
Richard B. Kreckel