<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 - miscompilation of for loop with a condition scope and continue statement"
href="https://bugs.llvm.org/show_bug.cgi?id=52440">52440</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>miscompilation of for loop with a condition scope and continue statement
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>All
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</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>C++
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>shevitz@lanl.gov
</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>I believe there is a very obscure miscompilation in clang when compiling a
`for` statement with both a condition scope and a continue statement. I am
including a minimal reproducer along with a .pdf file of the CFG that
demonstrates the problem.
The essence of the problem is that when there is a condition scope variable, a
continue statement branches to the wrong basic block. Referring to labels
visible in the CFG of the minimal_bug.pdf file, the continue statement in the
for body sets `%cleanup.dest.slot` to `4` which goes to the `%cleanup` basic
block. The `%cleanup` block does cleanups, then the code branches to the
`%for.inc` which sets `%cleanup.dest.slot% to 0 then branches back to
`%cleanup` and performs cleanups a second time. In short the destructor of a
non trivial condition scope variable is called twice because of the cycle in
the CFG between `%cleanup` and `%for.inc`.
While calling a destructor twice on the same object doesn't seem to inherently
cause a problem, a double free causes a core dump. The minimal_bug example is
constructed to cause a double free of a non-trivial condition scope variable so
the executable core dumps.
The solution to the miscompilation is to have the continue statement branch to
`%for.inc` rather than `%cleanup`. That way the cleanups are only done once.
The bug is obvious at optimization level 0, but I believe is there at all
optimization levels.
I am uploading a .pdf of the CFG generated by the minimal reproducer
demonstrating the bug. I seem to be able to only include one attachment, so I
will include the source inline:
//////////////////////////////////////////////////////////////////////
// minimal_bug.cpp
// This is a reproducer for the double free core dump in "for" codegen
struct S2 {
int x;
};
struct S {
S(int x=0):x(x) {s2=new S2;}
~S() {delete s2;}
int x;
S2* s2;
operator bool() {return x<5;}
};
int main () {
for (int i = 4; S s{i}; ++i) continue;
return 0;
}
//////////////////////////////////////////////////////////////////////
compile with (The executable will core dump):
clang++ -fno-exceptions -O0 minimal_bug.cpp
To generate the IR:
clang++ -fno-exceptions -O0 -S -emit-llvm minimal_bug.cpp
To generate the CFG:
opt -dot-cfg minimal_bug.ll
dot -Tpdf -o minimal_bug.pdf .main.dot -Gsize=8,10.5\!
Regards,
Danny</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>