http://bugzilla.suse.com/show_bug.cgi?id=934689 Bug ID: 934689 Summary: gcc (SUSE Linux) 4.8.3 20140627 compiler bug regarding integer constant Classification: openSUSE Product: openSUSE 12.3 Version: Final Hardware: Other OS: SLES 12 Status: NEW Severity: Normal Priority: P5 - None Component: Development Assignee: bnc-team-screening@forge.provo.novell.com Reporter: kees.dekker@infor.com QA Contact: qa-bugs@suse.de Found By: --- Blocker: --- Created attachment 637797 --> http://bugzilla.suse.com/attachment.cgi?id=637797&action=edit source file used for reproduction Contrary to prior gcc versions, gcc 4.8.3 of SLES 12 suffers from a bug when compiling in 64-bit mode. The compiler is not able to determine correctly whether something is a compile time constant and raises an error on something that IS a compile time constant. This version of gcc mistakenly handles this as an overflow. Consider the following code: <code> #include <stdio.h> #define cMaxUnsignedNBitValue(aBitCount) ((2ULL << ((aBitCount) - 1)) - 1ULL) #define cMaxSignedNBitValue(aBitCount) ((long long)cMaxUnsignedNBitValue((aBitCount) - 1LL)) #define cMinSignedNBitValue(aBitCount) (-cMaxSignedNBitValue(aBitCount) - 1) #define cMinSignedNByteValue(aByteCount) cMinSignedNBitValue(8 * (aByteCount)) #define cMinSignedValue(tType) ((tType)cMinSignedNByteValue(sizeof(tType))) #define cMinSignedValueAlt(tType) ((tType)cMinSignedNByteValue(sizeof(tType) == 8 ? 8 : sizeof(tType))) #define stringize(x) #x #define PrintExpression(x) \ printf( "expression `" #x "'\n" \ "expands to `%s'\n" \ "evaluates to %lld (%#llx)\n", \ stringize(x), \ (long long)(unsigned long long)(x), \ (unsigned long long)(x) \ ); \ printf( "it is %sless than zero\n", \ (x) < 0LL ? "" : "NOT " \ ); \ \ lValue = x; \ \ switch (lValue) { \ case x: \ printf("Match!\n"); \ break; \ default: \ printf("NO MATCH!\n"); \ break; \ } \ \ printf("\n"); int main() { long lValue; printf("hello, world\n"); PrintExpression(sizeof(int)) PrintExpression(sizeof(long)) PrintExpression(cMaxUnsignedNBitValue(32)) PrintExpression(cMaxUnsignedNBitValue(64)) PrintExpression(cMaxSignedNBitValue(32)) PrintExpression(cMaxSignedNBitValue(64)) PrintExpression(cMinSignedNBitValue(32)) PrintExpression(cMinSignedNBitValue(64)) PrintExpression(cMinSignedNByteValue(4)) PrintExpression(cMinSignedNByteValue(8)) PrintExpression(cMinSignedValue(int)) PrintExpression(cMinSignedValue(long)) // incorrect error or warning: overflow in constant expression [-fpermissive] PrintExpression(cMinSignedValueAlt(int)) PrintExpression(cMinSignedValueAlt(long)) printf("bye, world\n"); } </code> Code is also attached (cMinLongValue.cpp). When compiling without additional flags an error is raised: g++ -m64 cMinLongValue.cpp -o cMinLongValue64 cMinLongValue.cpp: In function 'int main()': cMinLongValue.cpp:11:77: error: overflow in constant expression [-fpermissive] #define cMinSignedValue(tType) ((tType)cMinSignedNByteValue(sizeof(tType))) ^ cMinLongValue.cpp:32:7: note: in definition of macro 'PrintExpression' case x: \ ^ cMinLongValue.cpp:64:18: note: in expansion of macro 'cMinSignedValue' PrintExpression(cMinSignedValue(long)) // incorrect error or warning: overflow in constant expression [-fpermissive] ^ cMinLongValue.cpp:11:77: error: overflow in constant expression [-fpermissive] #define cMinSignedValue(tType) ((tType)cMinSignedNByteValue(sizeof(tType))) ^ cMinLongValue.cpp:32:7: note: in definition of macro 'PrintExpression' case x: \ ^ cMinLongValue.cpp:64:18: note: in expansion of macro 'cMinSignedValue' PrintExpression(cMinSignedValue(long)) // incorrect error or warning: overflow in constant expression [-fpermissive] Adding the -fpermissive flag will relax the error to a warning: g++ -m64 -fpermissive cMinLongValue.cpp cMinLongValue.cpp: In function 'int main()': cMinLongValue.cpp:11:77: warning: overflow in constant expression [-fpermissive] #define cMinSignedValue(tType) ((tType)cMinSignedNByteValue(sizeof(tType))) ^ cMinLongValue.cpp:32:7: note: in definition of macro 'PrintExpression' case x: \ ^ cMinLongValue.cpp:64:18: note: in expansion of macro 'cMinSignedValue' PrintExpression(cMinSignedValue(long)) // incorrect error or warning: overflow in constant expression [-fpermissive] ^ cMinLongValue.cpp:11:77: warning: overflow in constant expression [-fpermissive] #define cMinSignedValue(tType) ((tType)cMinSignedNByteValue(sizeof(tType))) ^ cMinLongValue.cpp:32:7: note: in definition of macro 'PrintExpression' case x: \ ^ cMinLongValue.cpp:64:18: note: in expansion of macro 'cMinSignedValue' PrintExpression(cMinSignedValue(long)) // incorrect error or warning: overflow in constant expression [-fpermissive] ^ cMinLongValue.cpp:32:7: note: in definition of macro 'PrintExpression' case x: \ ^ cMinLongValue.cpp:64:18: note: in expansion of macro 'cMinSignedValue' PrintExpression(cMinSignedValue(long)) // incorrect error or warning: overflow in constant expression [-fpermissive] Excecuting the produced binary results in: ./a.out hello, world expression `sizeof(int)' expands to `sizeof(int)' evaluates to 4 (0x4) it is NOT less than zero Match! expression `sizeof(long)' expands to `sizeof(long)' evaluates to 8 (0x8) it is NOT less than zero Match! expression `cMaxUnsignedNBitValue(32)' expands to `((2ULL << ((32) - 1)) - 1ULL)' evaluates to 4294967295 (0xffffffff) it is NOT less than zero Match! expression `cMaxUnsignedNBitValue(64)' expands to `((2ULL << ((64) - 1)) - 1ULL)' evaluates to -1 (0xffffffffffffffff) it is NOT less than zero Match! expression `cMaxSignedNBitValue(32)' expands to `((long long)((2ULL << (((32) - 1LL) - 1)) - 1ULL))' evaluates to 2147483647 (0x7fffffff) it is NOT less than zero Match! expression `cMaxSignedNBitValue(64)' expands to `((long long)((2ULL << (((64) - 1LL) - 1)) - 1ULL))' evaluates to 9223372036854775807 (0x7fffffffffffffff) it is NOT less than zero Match! expression `cMinSignedNBitValue(32)' expands to `(-((long long)((2ULL << (((32) - 1LL) - 1)) - 1ULL)) - 1)' evaluates to -2147483648 (0xffffffff80000000) it is less than zero Match! expression `cMinSignedNBitValue(64)' expands to `(-((long long)((2ULL << (((64) - 1LL) - 1)) - 1ULL)) - 1)' evaluates to -9223372036854775808 (0x8000000000000000) it is less than zero Match! expression `cMinSignedNByteValue(4)' expands to `(-((long long)((2ULL << (((8 * (4)) - 1LL) - 1)) - 1ULL)) - 1)' evaluates to -2147483648 (0xffffffff80000000) it is less than zero Match! expression `cMinSignedNByteValue(8)' expands to `(-((long long)((2ULL << (((8 * (8)) - 1LL) - 1)) - 1ULL)) - 1)' evaluates to -9223372036854775808 (0x8000000000000000) it is less than zero Match! expression `cMinSignedValue(int)' expands to `((int)(-((long long)((2ULL << (((8 * (sizeof(int))) - 1LL) - 1)) - 1ULL)) - 1))' evaluates to -2147483648 (0xffffffff80000000) it is less than zero Match! expression `cMinSignedValue(long)' expands to `((long)(-((long long)((2ULL << (((8 * (sizeof(long))) - 1LL) - 1)) - 1ULL)) - 1))' evaluates to -9223372036854775808 (0x8000000000000000) it is less than zero Match! expression `cMinSignedValueAlt(int)' expands to `((int)(-((long long)((2ULL << (((8 * (sizeof(int) == 8 ? 8 : sizeof(int))) - 1LL) - 1)) - 1ULL)) - 1))' evaluates to -2147483648 (0xffffffff80000000) it is less than zero Match! expression `cMinSignedValueAlt(long)' expands to `((long)(-((long long)((2ULL << (((8 * (sizeof(long) == 8 ? 8 : sizeof(long))) - 1LL) - 1)) - 1ULL)) - 1))' evaluates to -9223372036854775808 (0x8000000000000000) it is less than zero Match! bye, world Note that using cMinSignedValue(long) results in a compile time error, while using cMinSignedValueAlt(long) works well. At runtime/execution level, evaluation is always correct. The difference between cMinSignedValue() and cMinSignedValueAlt() solves the issue, which is unexpected. -- You are receiving this mail because: You are on the CC list for the bug.