OSDN Git Service

PR middle-end/27793
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Jun 2006 09:21:30 +0000 (09:21 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Jun 2006 09:21:30 +0000 (09:21 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114607 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr26757.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr27894.C [new file with mode: 0644]

index f64c233..129f5df 100644 (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
index 7ded34f..ca8ff5f 100644 (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))
     {
index 77b9067..c0897a0 100644 (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.  */
index eb289d6..206fced 100644 (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));
index 187a41f..3de9999 100644 (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)
index 04c639a..9371ad6 100644 (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.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr26757.C b/gcc/testsuite/g++.dg/tree-ssa/pr26757.C
new file mode 100644 (file)
index 0000000..4d124e3
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr27894.C b/gcc/testsuite/g++.dg/tree-ssa/pr27894.C
new file mode 100644 (file)
index 0000000..ac97a35
--- /dev/null
@@ -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));
+}