http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50610
Bug #: 50610 Summary: G++ 4.4.3: Incorrect code at -O2 (-fwrapv, SafeInt, c++ templates, template class files) Classification: Unclassified Product: gcc Version: 4.4.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: other AssignedTo: unassig...@gcc.gnu.org ReportedBy: noloa...@gmail.com Created attachment 25407 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=25407 Test case for bad code generation at -O2 Attached is a test program which uses a secure vector. The secure vector 'has a' standard vector, and attempts to do a few extra things to help ensure safe use (such as check for pointer wrap and zeroization). In addition, the secure vector uses LeBlanc's SafeInt class to check for wraps and overflows. (SafeInt uses unsigned, so no undefined behavior should be present). The test program incorrectly rejects a valid input: $ g++ -g -O2 -fwrapv -I. TestMain.cpp SecureArray.cpp -o TestMain.exe $ ./TestMain.exe Array pointer wrap $ TestMain is as follows: try { const int arr[] = { 1, 1, 1, 1 }; SecureIntArray vv(arr, COUNTOF(arr)); assert(vv.size() == 4); } catch(const std::exception& ex) { cerr << ex.what() << endl; } The SecureIntArray ctor calls into a helper function: template <typename T> typename SecureArray<T>::SecureVector* SecureArray<T>::create_secure_array(const T* ptr, size_t cnt) { try { const size_t base = (size_t)ptr; SafeInt<size_t> si(cnt); si *= sizeof(T); si += base; } catch(const SafeIntException&) { throw InvalidArgumentException("Array pointer wrap"); } return new SecureVector(ptr /*first*/, ptr+cnt /*last*/); } *If* I manually check for overflow (ie, no SafeInt use), I get expected results: $ g++ -g -O2 -DSECURE_ARRAY_NO_SAFE_INT=1 -I. TestMain.cpp SecureArray.cpp -o TestMain.exe $ ./TestMain.exe $ Defining SECURE_ARRAY_NO_SAFE_INT uses the following rather than SafeInt objects: const size_t b = (size_t)ptr; size_t p = cnt * sizeof(T) + b; if(!(p >= b)) throw InvalidArgumentException("Array pointer wrap"); Finally, the issue is not present on other versions of GCC. Other versions include 4.5 from F14 and 4.6 from F15. I was not able to reduce the test program to something smaller (though I tried). For example, I know the following will not help the problem: removing namespaces, removing throws, removing explicit template instantiations, moving bodies into the header, and a few other items. I do know that removing everything except the ctor, size(), max_size(), and operator[] will fix it, but it does not help with a minimum test case.