<html>
<head>
<base href="http://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - std::numeric_limits<signed T>::is_modulo set even without -fwrapv"
href="http://llvm.org/bugs/show_bug.cgi?id=20158">20158</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>std::numeric_limits<signed T>::is_modulo set even without -fwrapv
</td>
</tr>
<tr>
<th>Product</th>
<td>libc++
</td>
</tr>
<tr>
<th>Version</th>
<td>3.4
</td>
</tr>
<tr>
<th>Hardware</th>
<td>Macintosh
</td>
</tr>
<tr>
<th>OS</th>
<td>MacOS X
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>All Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>myriachan@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvmbugs@cs.uiuc.edu, mclow.lists@gmail.com
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>std::numeric_limits<signed T>::is_modulo is true for integral types T when it
should not be, due to clang considering signed integer overflow to be undefined
and making optimizations on the basis of this assumption.
The following code demonstrates this flaw (Yosemite beta, Xcode 6 beta).
#include <stdio.h>
#include <limits>
__attribute__((__noinline__))
bool WillIncrementOverflow(signed int x)
{
return x + 1 < x;
}
extern "C" int main()
{
static_assert(true, "use C++11 mode");
printf("%d %d\n",
WillIncrementOverflow((std::numeric_limits<signed int>::max)()),
std::numeric_limits<signed int>::is_modulo);
return 0;
}
Compile with (yes, optimizations required):
clang++ -arch x86_64 -O3 test.cpp -o test
Outputs:
0 1
If you disable optimizations or add -fwrapv:
1 1
By the language of the C++11 standard, this is in violation. is_modulo on
signed integer types essentially indicates that the implementation considers
signed integer overflow and underflow to be well-defined, and that it wraps
essentially like you'd expect.
C++03 had a different definition for is_modulo: is_modulo indicated that a type
*may* wrap. In C++11, is_modulo indicates that it *will* wrap, and in a
very-specific, well-defined manner.
As the above program demonstrates, clang assumes that signed integer overflow
is undefined, and so it is incorrect to set is_modulo to true on signed integer
types. It should be false unless -fwrapv is used. However, with the
One-Definition Rule, that is likely to cause problems if a single module has
some translation units with -fwrapv and some without.
GCC's libstdc++ solution was to always set is_modulo to false:
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=22200">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=22200</a> Visual C++ seems to
fully-define signed integer overflow/underflow, so its setting of is_modulo to
true appears to be correct.
Melissa</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>