aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-06-13 11:21:30 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2006-06-13 11:21:30 +0200
commit10827cd8b31a8ced2cf6fbd6e4b902628c9a4ceb (patch)
treedb3fc5592b68d1ca71570ab74208c662419bc2e0 /gcc/cp
parentcd8d4e24e0b04c77dd709aeea7075d0a6a0f2833 (diff)
downloadgcc-10827cd8b31a8ced2cf6fbd6e4b902628c9a4ceb.zip
gcc-10827cd8b31a8ced2cf6fbd6e4b902628c9a4ceb.tar.gz
gcc-10827cd8b31a8ced2cf6fbd6e4b902628c9a4ceb.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-gimplify.c37
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/decl.c1
-rw-r--r--gcc/cp/name-lookup.c26
5 files changed, 82 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f64c233c..129f5df 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 7ded34f..ca8ff5f 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -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))
{
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 77b9067..c0897a0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index eb289d6..206fced 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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));
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 187a41f..3de9999 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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)