This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
bug in g++ front-end
- From: Alexey Starovoytov <Alexey dot Starovoytov at Sun dot COM>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 14 Sep 2007 18:15:26 -0700 (PDT)
- Subject: bug in g++ front-end
Hi,
looks like there is an ugly bug in g++ front-end.
the problem can be demonstrated by the existing testcase:
ext/pb_ds/regression/trie_data_map_rand.cc
if you apply the following diff:
.../libstdc++-v3/testsuite/util/regression/rand/assoc/detail/ $ svn di
Index: insert_fn_imps.hpp
===================================================================
--- insert_fn_imps.hpp (revision 10694)
+++ insert_fn_imps.hpp (working copy)
@@ -58,6 +58,7 @@
value_type v = test_traits::generate_value(m_g, m_m);
m_alloc.set_throw_prob(m_tp);
const_key_reference r_k = test_traits::extract_key(v);
+ std::cerr << (int*)0xDEADbeaf << std::endl;
typename cntnr::const_point_iterator found_it = m_p_c->find(r_k);
const bool existed = (found_it != m_p_c->end());
const std::pair<typename cntnr::point_iterator, bool> ins_ret =
m_p_c->insert(v);
trie_data_map_rand.cc will fail on sparc and x86 after random number
of 'deadbeaf' printouts compiled with -O0.
Looks like at least 4.2.x and most recent trunk are affected.
Look into the -fdump-tree-gimple dump for the following function:
static typename Cntnr::const_key_reference
pb_ds::test::detail::regression_test_type_traits<Cntnr>::extract_key
(typename Cntnr::const_reference)
there you'll see that temporary object of 'struct pair' is created
and it's address passed into extract_key_imp() function.
The source code comes from here:
.../libstdc++-v3/testsuite/util/regression/trait/assoc/ $ svn di
Index: type_trait.hpp
===================================================================
--- type_trait.hpp (revision 10694)
+++ type_trait.hpp (working copy)
@@ -79,7 +79,7 @@
static const_key_reference
extract_key(const_reference r_val)
- { return extract_key_imp(r_val); }
+ { return extract_key_imp(r_val); } // bug here
private:
typedef typename cntnr::allocator::template rebind<basic_type>::other
The mechanism of the bug is the following:
"r_k = test_traits::extract_key(v);" in insert_fn_imps.hpp eventually calls
"extract_key()" from type_trait.hpp above which creates a temp variable of
type "struct pair<basic_type,basic_type>" on stack and calls extract_key_imp()
with the address of that variable.
The returned address is actually the address of that stack temp variable,
so at the end 'r_k' points to already freed stack space.
Without '0xDEADbeaf' printout "m_p_c->find(r_k);" has a shorter
call chain than "extract_key()" and "find(r_k)" doesn't overwrite that
stack space, 'r_k' value is valid and everything works.
'deadbeaf' printout reuses that stack space and when it comes to
"m_p_c->find(r_k)", 'r_k' points to trash and 'find' sooner or later
coredumps.
Unfortunately I wasn't able to create a shorter testcase out of
trie_data_map_rand.cc
Various combination of
detail::regression_test_type_traits<s>::extract_key (ref);
with different 's' and 'ref' didn't expose the creation of such
extra temp variable.
As the summary 'extract_key' is supposed to look like:
static typename Cntnr::const_key_reference
pb_ds::test::detail::regression_test_type_traits<Cntnr>::extract_key
(typename Cntnr::const_reference) [with Cntnr = ...] (r_val)
{
const struct basic_type & D.82957;
const struct basic_type & D.82958;
D.82958 = extract_key_imp (r_val);
D.82957 = D.82958;
return D.82957;
}
incorrect 'extract_key' may look like:
static typename Cntnr::const_key_reference
pb_ds::test::detail::regression_test_type_traits<Cntnr>::extract_key
(typename Cntnr::const_reference) [with Cntnr = ...] (r_val)
{
const struct basic_type & D.107098;
const struct pair D.107097;
struct pair * D.107099;
const struct basic_type & D.107100;
__comp_ctor (&D.107097, r_val);
try
{
D.107100 = extract_key_imp (&D.107097);
D.107098 = D.107100;
return D.107098;
}
finally
{
D.107099 = (struct pair *) &D.107097;
__comp_dtor (D.107099);
}
}
thoughts ?
Thanks!
Alex.