decl.c (qualify_lookup): Handle templates.
authorJason Merrill <jason@yorick.cygnus.com>
Thu, 16 Jul 1998 21:16:06 +0000 (21:16 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 16 Jul 1998 21:16:06 +0000 (17:16 -0400)
* decl.c (qualify_lookup): Handle templates.
* decl2.c (do_using_directive): Don't pass ancestor.
* decl.c (push_using_directive): Calculate ancestor.
* decl2.c (do_nonmember_using_decl): Allow for type shadowing.
* decl.c (pushdecl): Move type shadowing handling from here...
(duplicate_decls): ...to here.
* decl.c (set_identifier_local_value_with_scope): New fn.
(pushdecl): Use it.
(set_identifier_local_value, lookup_type_current_level): New fns.
* decl2.c (do_local_using_decl): Handle types and binding level
stuff properly.

From-SVN: r21223

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c

index 85e8e05490c8cbd3c3b785950fb149eae28acf63..20e6653c630ddd32374aff7f3920f9533d51ac9d 100644 (file)
@@ -1,5 +1,19 @@
 1998-07-16  Jason Merrill  <jason@yorick.cygnus.com>
 
+       * decl.c (qualify_lookup): Handle templates.
+
+       * decl2.c (do_using_directive): Don't pass ancestor.
+       * decl.c (push_using_directive): Calculate ancestor.
+
+       * decl2.c (do_nonmember_using_decl): Allow for type shadowing.
+       * decl.c (pushdecl): Move type shadowing handling from here...
+       (duplicate_decls): ...to here.
+       * decl.c (set_identifier_local_value_with_scope): New fn.
+       (pushdecl): Use it.
+       (set_identifier_local_value, lookup_type_current_level): New fns.
+       * decl2.c (do_local_using_decl): Handle types and binding level
+       stuff properly.
+
        * init.c (build_offset_ref): Don't call mark_used on an OVERLOAD.
        * decl.c (select_decl): Extract a lone function from an OVERLOAD.
        (lookup_namespace_name): Likewise.
index 3f8840a7609b3bd5bf917c2ab869aaab39e5360d..f6c1e23bdd6f337dba0b82f5f905496b8c4e7b61 100644 (file)
@@ -2379,7 +2379,7 @@ extern void pushdecl_nonclass_level               PROTO((tree));
 #endif
 extern tree pushdecl_namespace_level            PROTO((tree));
 extern tree push_using_decl                     PROTO((tree, tree));
-extern tree push_using_directive                PROTO((tree, tree));
+extern tree push_using_directive                PROTO((tree));
 extern void push_class_level_binding           PROTO((tree, tree));
 extern tree push_using_decl                     PROTO((tree, tree));
 extern tree implicitly_declare                 PROTO((tree));
@@ -2403,9 +2403,11 @@ extern tree lookup_name_nonclass         PROTO((tree));
 extern tree lookup_function_nonclass            PROTO((tree, tree));
 extern tree lookup_name                                PROTO((tree, int));
 extern tree lookup_name_current_level          PROTO((tree));
+extern tree lookup_type_current_level          PROTO((tree));
 extern tree lookup_name_namespace_only          PROTO((tree));
 extern void begin_only_namespace_names          PROTO((void));
 extern void end_only_namespace_names            PROTO((void));
+extern tree namespace_ancestor                 PROTO((tree, tree));
 extern int  lookup_using_namespace              PROTO((tree,tree,tree,tree,int));
 extern int  qualified_lookup_using_namespace    PROTO((tree,tree,tree,int));
 extern tree auto_function                      PROTO((tree, tree, enum built_in_function));
index 8071386c22ad8abb31bb4f7bb687a71d3204e72c..478d75b0e011b93f8e297cbe487a6fba8e078c80 100644 (file)
@@ -2159,6 +2159,26 @@ set_identifier_type_value (id, type)
   set_identifier_type_value_with_scope (id, type, inner_binding_level);
 }
 
+void
+set_identifier_local_value_with_scope (id, val, b)
+     tree id, val;
+     struct binding_level *b;
+{
+  tree oldlocal;
+  my_friendly_assert (! b->namespace_p, 980716);
+
+  oldlocal = IDENTIFIER_LOCAL_VALUE (id);
+  b->shadowed = tree_cons (id, oldlocal, b->shadowed);
+  IDENTIFIER_LOCAL_VALUE (id) = val;
+}
+
+void
+set_identifier_local_value (id, val)
+     tree id, val;
+{
+  set_identifier_local_value_with_scope (id, val, current_binding_level);
+}
+
 /* Return the type associated with id. */
 
 tree
@@ -2646,12 +2666,30 @@ duplicate_decls (newdecl, olddecl)
     }
   else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
+      if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
+          && TREE_CODE (newdecl) != TYPE_DECL
+          && ! (TREE_CODE (newdecl) == TEMPLATE_DECL
+                && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
+         || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
+             && TREE_CODE (olddecl) != TYPE_DECL
+             && ! (TREE_CODE (olddecl) == TEMPLATE_DECL
+                   && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+                       == TYPE_DECL))))
+       {
+         /* We do nothing special here, because C++ does such nasty
+            things with TYPE_DECLs.  Instead, just let the TYPE_DECL
+            get shadowed, and know that if we need to find a TYPE_DECL
+            for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+            slot of the identifier.  */
+         return 0;
+       }
+
       if ((TREE_CODE (newdecl) == FUNCTION_DECL
           && DECL_FUNCTION_TEMPLATE_P (olddecl))
          || (TREE_CODE (olddecl) == FUNCTION_DECL
              && DECL_FUNCTION_TEMPLATE_P (newdecl)))
        return 0;
-      
+
       cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
       if (TREE_CODE (olddecl) == TREE_LIST)
        olddecl = TREE_VALUE (olddecl);
@@ -3319,24 +3357,7 @@ pushdecl (x)
            }
          else if (TREE_CODE (t) != TREE_CODE (x))
            {
-             if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
-                  && TREE_CODE (x) != TYPE_DECL
-                  && ! (TREE_CODE (x) == TEMPLATE_DECL
-                        && TREE_CODE (DECL_TEMPLATE_RESULT (x)) == TYPE_DECL))
-                 || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
-                     && TREE_CODE (t) != TYPE_DECL
-                     && ! (TREE_CODE (t) == TEMPLATE_DECL
-                           && (TREE_CODE (DECL_TEMPLATE_RESULT (t))
-                               == TYPE_DECL))))
-               {
-                 /* We do nothing special here, because C++ does such nasty
-                    things with TYPE_DECLs.  Instead, just let the TYPE_DECL
-                    get shadowed, and know that if we need to find a TYPE_DECL
-                    for a given name, we can look in the IDENTIFIER_TYPE_VALUE
-                    slot of the identifier.  */
-                 ;
-               }
-             else if (duplicate_decls (x, t))
+             if (duplicate_decls (x, t))
                return t;
            }
          else if (duplicate_decls (x, t))
@@ -3519,10 +3540,7 @@ pushdecl (x)
          if (TREE_CODE (x) != TYPE_DECL
              || t == NULL_TREE
              || ! DECL_ARTIFICIAL (x))
-           {
-             b->shadowed = tree_cons (name, oldlocal, b->shadowed);
-             IDENTIFIER_LOCAL_VALUE (name) = x;
-           }
+           set_identifier_local_value_with_scope (name, x, b);
 
          /* If this is a TYPE_DECL, push it into the type value slot.  */
          if (TREE_CODE (x) == TYPE_DECL)
@@ -3851,12 +3869,11 @@ push_using_decl (scope, name)
    TREE_LIST otherwise.  */
 
 tree
-push_using_directive (used, ancestor)
+push_using_directive (used)
      tree used;
-     tree ancestor;
 {
   tree ud = current_binding_level->using_directives;
-  tree iter;
+  tree iter, ancestor;
   
   /* Check if we already have this. */
   if (purpose_member (used, ud) != NULL_TREE)
@@ -3864,8 +3881,9 @@ push_using_directive (used, ancestor)
 
   /* Recursively add all namespaces used. */
   for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
-    push_using_directive (TREE_PURPOSE (iter), ancestor);
+    push_using_directive (TREE_PURPOSE (iter));
 
+  ancestor = namespace_ancestor (current_decl_namespace (), used);
   ud = current_binding_level->using_directives;
   ud = perm_tree_cons (used, ancestor, ud);
   current_binding_level->using_directives = ud;
@@ -4859,7 +4877,10 @@ qualify_lookup (val, flags)
     return val;
   if (LOOKUP_NAMESPACES_ONLY (flags) && TREE_CODE (val) != NAMESPACE_DECL)
     return NULL_TREE;
-  if (LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL)
+  if (LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
+      && ! ((flags & LOOKUP_TEMPLATES_EXPECTED)
+           && TREE_CODE (val) == TEMPLATE_DECL
+           && DECL_CLASS_TEMPLATE_P (val)))
     return NULL_TREE;
   return val;
 }
@@ -5133,16 +5154,41 @@ lookup_name_current_level (name)
       struct binding_level *b = current_binding_level;
       while (1)
        {
-         for (t = b->names; t; t = TREE_CHAIN (t))
-           if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
-             goto out;
+         if (purpose_member (name, b->shadowed))
+           return IDENTIFIER_LOCAL_VALUE (name);
+         if (b->keep == 2)
+           b = b->level_chain;
+         else
+           break;
+       }
+    }
+
+  return t;
+}
+
+/* Like lookup_name_current_level, but for types.  */
+
+tree
+lookup_type_current_level (name)
+     tree name;
+{
+  register tree t = NULL_TREE;
+
+  my_friendly_assert (! current_binding_level->namespace_p, 980716);
+
+  if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
+      && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
+    {
+      struct binding_level *b = current_binding_level;
+      while (1)
+       {
+         if (purpose_member (name, b->type_shadowed))
+           return REAL_IDENTIFIER_TYPE_VALUE (name);
          if (b->keep == 2)
            b = b->level_chain;
          else
            break;
        }
-    out:
-      ;
     }
 
   return t;
index 5384e98e066ede672b238747c40bf6b6b0b99ced..6713c65834b610e13032b596a963fa05e41118d9 100644 (file)
@@ -58,7 +58,6 @@ static int finish_vtable_vardecl PROTO((tree, tree));
 static int prune_vtable_vardecl PROTO((tree, tree));
 static void finish_sigtable_vardecl PROTO((tree, tree));
 static int is_namespace_ancestor PROTO((tree, tree));
-static tree namespace_ancestor PROTO((tree, tree));
 static void add_using_namespace PROTO((tree, tree, int));
 static tree ambiguous_decl PROTO((tree, tree, tree,int));
 static tree build_anon_union_vars PROTO((tree, tree*, int, int));
@@ -3839,7 +3838,7 @@ is_namespace_ancestor (root, child)
 /* Return the namespace that is the common ancestor 
    of two given namespaces. */
 
-static tree
+tree
 namespace_ancestor (ns1, ns2)
      tree ns1, ns2;
 {
@@ -4495,10 +4494,16 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
   if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
     {
       tree tmp, tmp1;
+
+      if (oldval && !is_overloaded_fn (oldval))
+       {
+         duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval);
+         oldval = NULL_TREE;
+       }
+
       *newval = oldval;
       for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
        {
-
          /* Compare each new function with each old one.
             If the old function was also used, there is no conflict. */
          for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
@@ -4522,8 +4527,8 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
   else 
     {
       *newval = BINDING_VALUE (decls);
-      if (oldval && oldval != *newval && !duplicate_decls (*newval, oldval))
-       *newval = oldval;
+      if (oldval)
+       duplicate_decls (*newval, oldval);
     } 
 
   *newtype = BINDING_TYPE (decls);
@@ -4563,27 +4568,28 @@ do_toplevel_using_decl (decl)
   return;
 }
 
+/* Process a using-declaration at function scope.  */
+
 void
 do_local_using_decl (decl)
      tree decl;
 {
   tree scope, name;
   tree oldval, oldtype, newval, newtype;
+
   decl = validate_nonmember_using_decl (decl, &scope, &name);
   if (decl == NULL_TREE)
     return;
 
-  /* XXX nested values */
-  oldval = IDENTIFIER_LOCAL_VALUE (name);
-  /* XXX get local type */
-  oldtype = NULL_TREE;
+  oldval = lookup_name_current_level (name);
+  oldtype = lookup_type_current_level (name);
 
   do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
 
   if (newval)
-    /* XXX update bindings */
-    IDENTIFIER_LOCAL_VALUE (name) = newval;
-  /* XXX type */
+    set_identifier_local_value (name, newval);
+  if (newtype)
+    set_identifier_type_value (name, newtype);
 }
 
 tree
@@ -4638,9 +4644,7 @@ do_using_directive (namespace)
     }
   namespace = ORIGINAL_NAMESPACE (namespace);
   if (!toplevel_bindings_p ())
-    push_using_directive
-      (namespace, namespace_ancestor (current_decl_namespace(), 
-                                     current_namespace));
+    push_using_directive (namespace);
   else
     /* direct usage */
     add_using_namespace (current_namespace, namespace, 0);