re PR c++/41090 (Using static label reference in c++ class constructor produces wrong code)

PR c++/41090
	* decl.c (cp_finish_decl): Add local statics to cfun->local_decls.
	* optimize.c (clone_body): Remap their initializers when making base
	variants.
	(maybe_clone_body): Complain if multiple clones aren't safe.

From-SVN: r156455
This commit is contained in:
Jason Merrill 2010-02-02 19:07:49 -05:00 committed by Jason Merrill
parent 80ec737fd0
commit e6ca6e2a1f
5 changed files with 77 additions and 1 deletions

View File

@ -1,3 +1,11 @@
2010-02-02 Jason Merrill <jason@redhat.com>
PR c++/41090
* decl.c (cp_finish_decl): Add local statics to cfun->local_decls.
* optimize.c (clone_body): Remap their initializers when making base
variants.
(maybe_clone_body): Complain if multiple clones aren't safe.
2010-01-29 Dodji Seketeli <dodji@redhat.com>
PR c++/42758

View File

@ -5743,7 +5743,18 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
if (DECL_FUNCTION_SCOPE_P (decl)
&& TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl))
push_local_name (decl);
{
push_local_name (decl);
if (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl))
/* Normally local_decls is populated during GIMPLE lowering,
but [cd]tors are never actually compiled directly. We need
to put statics on the list so we can deal with the label
address extension. */
cfun->local_decls = tree_cons (NULL_TREE, decl,
cfun->local_decls);
}
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
if (!DECL_INITIALIZED_P (decl)

View File

@ -104,6 +104,21 @@ clone_body (tree clone, tree fn, void *arg_map)
stmts = DECL_SAVED_TREE (fn);
walk_tree (&stmts, copy_tree_body_r, &id, NULL);
/* Also remap the initializer of any static variables so that they (in
particular, any label addresses) correspond to the base variant rather
than the abstract one. */
if (DECL_NAME (clone) == base_dtor_identifier
|| DECL_NAME (clone) == base_ctor_identifier)
{
tree decls = DECL_STRUCT_FUNCTION (fn)->local_decls;
for (; decls; decls = TREE_CHAIN (decls))
{
tree decl = TREE_VALUE (decls);
walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
}
}
append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
}
@ -195,6 +210,7 @@ maybe_clone_body (tree fn)
bool first = true;
bool in_charge_parm_used;
int idx;
bool need_alias = false;
/* We only clone constructors and destructors. */
if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
@ -223,6 +239,11 @@ maybe_clone_body (tree fn)
else
gcc_unreachable ();
/* Remember if we can't have multiple clones for some reason. We need to
check this before we remap local static initializers in clone_body. */
if (!tree_versionable_function_p (fn))
need_alias = true;
/* We know that any clones immediately follow FN in the TYPE_METHODS
list. */
push_to_top_level ();
@ -314,6 +335,17 @@ maybe_clone_body (tree fn)
/* No need to populate body. */ ;
else
{
/* If we can't have multiple copies of FN (say, because there's a
static local initialized with the address of a label), we need
to use an alias for the complete variant. */
if (idx == 1 && need_alias)
{
if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
else
sorry ("making multiple clones of %qD", fn);
}
/* Remap the parameters. */
decl_map = pointer_map_create ();
for (parmno = 0,

View File

@ -1,3 +1,8 @@
2010-02-02 Jason Merrill <jason@redhat.com>
PR c++/41090
* g++.dg/ext/label13.C: New.
2010-02-02 Tobias Burnus <burnus@net-b.de>
PR fortran/42650

View File

@ -0,0 +1,20 @@
// PR c++/41090
// { dg-do run }
// { dg-options "" }
int i;
struct C
{
C()
{
static void *labelref = &&label;
goto *labelref;
label: i = 1;
}
};
int main()
{
C c;
return (i != 1);
}