re PR middle-end/27793 (num_ssa_names inconsistent or immediate use iterator wrong)

PR middle-end/27793
	* cp-tree.h (cxx_int_tree_map): New struct.
	(struct language_function): Add extern_decl_map field.
	* name-lookup.c (pushdecl_maybe_friend): Add x -> t mapping
	to cp_function_chain->extern_decl_map hash table instead of
	copying over DECL_UID.
	* cp-gimplify.c (cxx_int_tree_map_eq, cxx_int_tree_map_hash): New
	functions.
	(cp_genericize_r): Remap DECL_EXTERN local decls using
	cp_function_chain->extern_decl_map hash table.
	* decl.c (finish_function): Clear extern_decl_map.

	PR c++/26757
	PR c++/27894
	* g++.dg/tree-ssa/pr26757.C: New test.
	* g++.dg/tree-ssa/pr27894.C: New test.

From-SVN: r114607
This commit is contained in:
Jakub Jelinek 2006-06-13 11:21:30 +02:00 committed by Jakub Jelinek
parent cd8d4e24e0
commit 10827cd8b3
8 changed files with 214 additions and 6 deletions

View file

@ -1,3 +1,17 @@
2006-06-13 Jakub Jelinek <jakub@redhat.com>
PR middle-end/27793
* cp-tree.h (cxx_int_tree_map): New struct.
(struct language_function): Add extern_decl_map field.
* name-lookup.c (pushdecl_maybe_friend): Add x -> t mapping
to cp_function_chain->extern_decl_map hash table instead of
copying over DECL_UID.
* cp-gimplify.c (cxx_int_tree_map_eq, cxx_int_tree_map_hash): New
functions.
(cp_genericize_r): Remap DECL_EXTERN local decls using
cp_function_chain->extern_decl_map hash table.
* decl.c (finish_function): Clear extern_decl_map.
2006-06-12 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/27601

View file

@ -601,6 +601,24 @@ is_invisiref_parm (tree t)
&& DECL_BY_REFERENCE (t));
}
/* Return true if the uid in both int tree maps are equal. */
int
cxx_int_tree_map_eq (const void *va, const void *vb)
{
const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
return (a->uid == b->uid);
}
/* Hash a UID in a cxx_int_tree_map. */
unsigned int
cxx_int_tree_map_hash (const void *item)
{
return ((const struct cxx_int_tree_map *)item)->uid;
}
/* Perform any pre-gimplification lowering of C++ front end trees to
GENERIC. */
@ -620,6 +638,25 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
return NULL;
}
/* Map block scope extern declarations to visible declarations with the
same name and type in outer scopes if any. */
if (cp_function_chain->extern_decl_map
&& (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
&& DECL_EXTERNAL (stmt))
{
struct cxx_int_tree_map *h, in;
in.uid = DECL_UID (stmt);
h = (struct cxx_int_tree_map *)
htab_find_with_hash (cp_function_chain->extern_decl_map,
&in, in.uid);
if (h)
{
*stmt_p = h->to;
*walk_subtrees = 0;
return NULL;
}
}
/* Other than invisiref parms, don't walk the same tree twice. */
if (pointer_set_contains (p_set, stmt))
{

View file

@ -721,6 +721,15 @@ struct saved_scope GTY(())
extern GTY(()) struct saved_scope *scope_chain;
struct cxx_int_tree_map GTY(())
{
unsigned int uid;
tree to;
};
extern unsigned int cxx_int_tree_map_hash (const void *);
extern int cxx_int_tree_map_eq (const void *, const void *);
/* Global state pertinent to the current function. */
struct language_function GTY(())
@ -747,6 +756,7 @@ struct language_function GTY(())
htab_t GTY((param_is(struct named_label_entry))) x_named_labels;
struct cp_binding_level *bindings;
VEC(tree,gc) *x_local_names;
htab_t GTY((param_is (struct cxx_int_tree_map))) extern_decl_map;
};
/* The current C++-specific per-function global variables. */

View file

@ -11102,6 +11102,7 @@ finish_function (int flags)
f->x_vtt_parm = NULL;
f->x_return_value = NULL;
f->bindings = NULL;
f->extern_decl_map = NULL;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));

View file

@ -670,14 +670,28 @@ pushdecl_maybe_friend (tree x, bool is_friend)
if (decls_match (x, t))
/* The standard only says that the local extern
inherits linkage from the previous decl; in
particular, default args are not shared. We must
also tell cgraph to treat these decls as the same,
or we may neglect to emit an "unused" static - we
do this by making the DECL_UIDs equal, which should
be viewed as a kludge. FIXME. */
particular, default args are not shared. Add
the decl into a hash table to make sure only
the previous decl in this case is seen by the
middle end. */
{
struct cxx_int_tree_map *h;
void **loc;
TREE_PUBLIC (x) = TREE_PUBLIC (t);
DECL_UID (x) = DECL_UID (t);
if (cp_function_chain->extern_decl_map == NULL)
cp_function_chain->extern_decl_map
= htab_create_ggc (20, cxx_int_tree_map_hash,
cxx_int_tree_map_eq, NULL);
h = GGC_NEW (struct cxx_int_tree_map);
h->uid = DECL_UID (x);
h->to = t;
loc = htab_find_slot_with_hash
(cp_function_chain->extern_decl_map, h,
h->uid, INSERT);
*(struct cxx_int_tree_map **) loc = h;
}
}
else if (TREE_CODE (t) == PARM_DECL)

View file

@ -1,3 +1,9 @@
2006-06-13 Jakub Jelinek <jakub@redhat.com>
PR c++/27894
* g++.dg/tree-ssa/pr26757.C: New test.
* g++.dg/tree-ssa/pr27894.C: New test.
2006-06-13 Maxim Kuvyrkov <mkuvyrkov@ispras.ru>
* gcc.c-torture/compile/20060609-1.c: New test.

View file

@ -0,0 +1,44 @@
// PR c++/26757
// { dg-do run }
// { dg-options "-O" }
extern "C" void abort ();
typedef struct A
{
int c;
int d;
} A;
A *b;
void
foo ()
{
b->c++;
extern A *b;
b->d++;
}
void
bar ()
{
if (b->d)
b->c++;
}
int
main ()
{
A a = { 0, 0 };
b = &a;
foo ();
bar ();
if (b->c != 2)
abort ();
if (b->d != 1)
abort ();
return 0;
}

View file

@ -0,0 +1,82 @@
// PR c++/27894
// { dg-do compile }
// { dg-options "-O" }
class A;
struct B
{
B (unsigned long);
int b2 () const;
A *b1 () const;
};
enum { P = 0 };
enum O { Q = 75, };
class C;
struct D { A *d; };
struct E
{
B e1 (int) const;
A *e2 (const B &) const;
D e3[4096];
};
inline A *
E::e2 (const B & x) const
{
const D *w = &e3[x.b2 ()];
return (A *) w->d;
}
extern E *e;
inline A *
B::b1 () const
{
extern E *e;
return e->e2 (*this);
}
template <class T> struct F : public B
{
F (const B &);
T *b1 () const;
};
template < class T > inline T * F <T>::b1 () const
{
return (T *) B::b1 ();
};
typedef F <C> N;
class G {};
class H : public G {};
class I : public H {};
class J {};
class K {};
struct L
{
void l (J *, C *, int, const char *, O);
};
class M : public K, public I
{
void m (J &, int, const char *);
void m (J &, int, int, const char *, float);
};
void
M::m (J &x, int y, const char *z)
{
L *w = new L;
N v = e->e1 (y);
w->l (&x, v.b1 (), P, z, Q);
}
void
M::m (J &x, int y, int s, const char *z, float t)
{
L *w = new L;
N v = e->e1 (y);
w->l (&x, v.b1 (), s, z, (O) (int) ((t) ? (50 + 20 / (float) t) : 0));
}