mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-02 05:40:26 +08:00
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:
parent
80ec737fd0
commit
e6ca6e2a1f
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
20
gcc/testsuite/g++.dg/ext/label13.C
Normal file
20
gcc/testsuite/g++.dg/ext/label13.C
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user