<html>
<head>
<base href="https://bugs.llvm.org/">
</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 - Dangerous fld usage"
href="https://bugs.llvm.org/show_bug.cgi?id=44302">44302</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Dangerous fld usage
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>C++
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>zamazan4ik@tut.by
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, dgregor@apple.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>clang(trunk) with '-O3 -m32' for this code:
#include <stdint.h>
typedef int SQObjectType;
typedef int64_t SQInteger;
union SQObjectValue
{
SQInteger integer;
float real;
};
struct SQObject
{
SQObjectType _type;
SQObjectValue _unVal;
};
SQInteger toint(SQObject &i)
{
return i._type == 10 ? (SQInteger)(i._unVal.real) :
(i._unVal.integer);
}
generates that assembly:
toint(SQObject&): # @toint(SQObject&)
sub esp, 20
mov ecx, dword ptr [esp + 24]
movss xmm0, dword ptr [ecx + 4
movss dword ptr [esp + 8], xmm0
fld dword ptr [esp + 8] #here floating point exception will be
thrown, if provided tagged union is int64_t == -1
fnstcw word ptr [esp + 4]
movzx eax, word ptr [esp + 4]
or eax, 3072
mov word ptr [esp + 6], ax
fldcw word ptr [esp + 6]
fistp qword ptr [esp + 8]
fldcw word ptr [esp + 4]
cmp dword ptr [ecx], 10
jne .LBB0_1
mov eax, dword ptr [esp + 8]
mov edx, dword ptr [esp + 12]
add esp, 20
ret
.LBB0_1:
mov eax, dword ptr [ecx + 4]
mov edx, dword ptr [ecx + 8]
add esp, 20
ret
gcc(trunk) with '-O3 -m32' generates this:
toint(SQObject&):
sub esp, 20
mov eax, DWORD PTR [esp+24]
cmp DWORD PTR [eax], 10 #first compare for type, than do float to
int64_t conversion!
je .L7
mov edx, DWORD PTR [eax+8]
mov eax, DWORD PTR [eax+4]
add esp, 20
ret
.L7:
fld DWORD PTR [eax+4]
fnstcw WORD PTR [esp+14]
movzx eax, WORD PTR [esp+14]
or ah, 12
mov WORD PTR [esp+12], ax
fldcw WORD PTR [esp+12]
fistp QWORD PTR [esp]
fldcw WORD PTR [esp+14]
mov eax, DWORD PTR [esp]
mov edx, DWORD PTR [esp+4]
add esp, 20
ret
So, first of all clang generates dangerous code that will result in
unconditional floating point conversion even if provided SQObject is actually
an Integer (of certain values).
Secondly, gcc code is slightly more optimal (not important).
In addition, version with pointer to SqObject is for some reason works
correctly, unlike reference.
(But it is not possible to workaround buggy code generation by getting pointer
to reference, probably due to inlining).
Live code example : <a href="https://godbolt.org/z/gHf9YZ">https://godbolt.org/z/gHf9YZ</a></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>