This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH RFC: PR 33094: Test DECL_INITIAL in make_rtl_for_nonlocal_decl
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 17 Aug 2007 08:23:59 -0700
- Subject: PATCH RFC: PR 33094: Test DECL_INITIAL in make_rtl_for_nonlocal_decl
PR 33094 is about a small C++ test case which mixes anonymous
namespaces, templates, virtual methods, and initialized static const
members to create an ICE.
namespace
{
template <typename T>
class A
{
virtual T f1() { return c; }
static const T c = 0;
};
A<int> v;
}
The ICE occurs here in make_rtl_for_nonlocal_decl in cp/decl.c:
/* An in-class declaration of a static data member should be
external; it is only a declaration, and not a definition. */
if (init == NULL_TREE)
gcc_assert (DECL_EXTERNAL (decl));
make_rtl_for_nonlocal_decl is called by cp_finish_decl.
cp_finish_decl is called with a non-NULL INIT parameter.
cp_finish_decl does this:
init = check_initializer (decl, init, flags, &cleanup);
check_initializer sees that the type in question (int) does not
require a constructor, and winds up doing this:
init_code = store_init_value (decl, init);
and returning NULL. store_init_value puts the value into DECL_INITIAL
of DECL.
All those steps seem reasonable. If the anonymous namespace is
removed from the test case, all is well because DECL_EXTERNAL is set.
When using the anonymous namespace, DECL_EXTERNAL is not set.
Specifically, it is cleared in cp_write_global_declarations:
/* If this static data member is needed, provide it to the
back end. */
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
DECL_EXTERNAL (decl) = 0;
The DECL_NOT_REALLY_EXTERN flag is only set when using an anonymous
namespace. It happens in constrain_visibility:
if (visibility == VISIBILITY_ANON)
{
/* extern "C" declarations aren't affected by the anonymous
namespace. */
if (!DECL_EXTERN_C_P (decl))
{
TREE_PUBLIC (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
if (DECL_LANG_SPECIFIC (decl))
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
}
To sum up: the test in make_rtl_for_nonlocal_decl does not consider
the possibility that the initializer might be in DECL_INITIAL. This
normally works because static class members normally have
DECL_EXTERNAL set. However, when an anonymous namespace is used
DECL_EXTERNAL is cleared.
Given the above, this patch fixes the problem. I ran a bootstrap and
check-g++ on i686-pc-linux-gnu.
Does this look OK?
Ian
2007-08-17 Ian Lance Taylor <iant@google.com>
PR c++/33094
* decl.c (make_rtl_for_nonlocal_decl): Test DECL_INITIAL as well
as init.
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 127491)
+++ cp/decl.c (working copy)
@@ -4963,7 +4963,7 @@ make_rtl_for_nonlocal_decl (tree decl, t
gcc_assert (TREE_STATIC (decl));
/* An in-class declaration of a static data member should be
external; it is only a declaration, and not a definition. */
- if (init == NULL_TREE)
+ if (init == NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
gcc_assert (DECL_EXTERNAL (decl));
}