decl.c (qualify_lookup): New fn.
authorJason Merrill <jason@gcc.gnu.org>
Thu, 16 Jul 1998 16:38:26 +0000 (12:38 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 16 Jul 1998 16:38:26 +0000 (12:38 -0400)
* decl.c (qualify_lookup): New fn.
(lookup_name_real): Use it.
* decl2.c (add_using_namespace): When directly using a namespace
that was indirect before, promote it.
* cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES,
LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY,
LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros.
* decl.c (select_decl): Replace two flag parameters by one.
(unqualified_namespace_lookup): Likewise, pass flag.
(lookup_flags): New function.
(lookup_name_real): Compute flags, pass them.
(lookup_namespace_name): Call with zero-flag.
* decl2.c (ambiguous_decl): Add flag parameter, complain only
according to flags.
(lookup_using_namespace, qualified_lookup_using_namespace):
Add flag parameter, pass them through.
* lex.c (do_scoped_id): Call with zero-flag.

From-SVN: r21218

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

index 749bf212579b0ccb292ee75d56a9222f5f0752fc..1abd30d818db92e5c14c2518ef9db8ae068c273a 100644 (file)
@@ -1,3 +1,27 @@
+1998-07-16  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (qualify_lookup): New fn.
+       (lookup_name_real): Use it.
+
+1998-07-16  Martin v. Loewis  <loewis@informatik.hu-berlin.de>
+
+       * decl2.c (add_using_namespace): When directly using a namespace
+       that was indirect before, promote it.
+
+       * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES,
+       LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY,
+       LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros.
+       * decl.c (select_decl): Replace two flag parameters by one.
+       (unqualified_namespace_lookup): Likewise, pass flag.
+       (lookup_flags): New function.
+       (lookup_name_real): Compute flags, pass them.
+       (lookup_namespace_name): Call with zero-flag.
+       * decl2.c (ambiguous_decl): Add flag parameter, complain only
+       according to flags.
+       (lookup_using_namespace, qualified_lookup_using_namespace):
+       Add flag parameter, pass them through.
+       * lex.c (do_scoped_id): Call with zero-flag.
+
 1998-07-16  Jason Merrill  <jason@yorick.cygnus.com>
 
        * typeck.c (convert_for_assignment): Use comptypes.
index 31098113b7c80d5bf95e48255c29215b06427f70..3f8840a7609b3bd5bf917c2ab869aaab39e5360d 100644 (file)
@@ -2174,7 +2174,16 @@ extern tree current_class_type;  /* _TYPE: the type of the current class */
    LOOKUP_NO_CONVERSION means that user-defined conversions are not
      permitted.  Built-in conversions are permitted.
    LOOKUP_DESTRUCTOR means explicit call to destructor.
-   LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references.  */
+   LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references.
+
+   These are used in global lookup to support elaborated types and
+   qualifiers.
+   
+   LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces.
+   LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types.
+   LOOKUP_PREFER_BOTH means class-or-namespace-name.
+   LOOKUP_TEMPLATES_EXPECTED means that class templates also count
+     as types.  */
 
 #define LOOKUP_PROTECT (1)
 #define LOOKUP_COMPLAIN (2)
@@ -2189,6 +2198,17 @@ extern tree current_class_type;  /* _TYPE: the type of the current class */
 #define LOOKUP_NO_CONVERSION (512)
 #define LOOKUP_DESTRUCTOR (512)
 #define LOOKUP_NO_TEMP_BIND (1024)
+#define LOOKUP_PREFER_TYPES (2048)
+#define LOOKUP_PREFER_NAMESPACES (4096)
+#define LOOKUP_PREFER_BOTH (6144)
+#define LOOKUP_TEMPLATES_EXPECTED (8192)
+
+#define LOOKUP_NAMESPACES_ONLY(f)  \
+  (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES))
+#define LOOKUP_TYPES_ONLY(f)  \
+  (!((f) & LOOKUP_PREFER_NAMESPACES) && ((f) & LOOKUP_PREFER_TYPES))
+#define LOOKUP_QUALIFIERS_ONLY(f)     ((f) & LOOKUP_PREFER_BOTH)
+     
 
 /* These flags are used by the conversion code.
    CONV_IMPLICIT   :  Perform implicit conversions (standard and user-defined).
@@ -2386,8 +2406,8 @@ extern tree lookup_name_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 int  lookup_using_namespace              PROTO((tree,tree,tree,tree));
-extern int  qualified_lookup_using_namespace    PROTO((tree,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));
 extern void init_decl_processing               PROTO((void));
 extern int init_type_desc                      PROTO((void));
index e3f226cac4d69e6e601900c09f69af10d63754ef..0801ab83a86bff38e427db22e4af06c09ec34832 100644 (file)
@@ -4646,7 +4646,7 @@ lookup_namespace_name (namespace, name)
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
   
   val = binding_init (&_b);
-  if (!qualified_lookup_using_namespace (name, namespace, val))
+  if (!qualified_lookup_using_namespace (name, namespace, val, 0))
     return error_mark_node;
 
   if (BINDING_VALUE (val))
@@ -4736,13 +4736,13 @@ make_typename_type (context, name)
 /* Select the right _DECL from multiple choices. */
 
 static tree
-select_decl (binding, prefer_type, namespaces_only)
+select_decl (binding, flags)
      tree binding;
-     int prefer_type, namespaces_only;
+     int flags;
 {
   tree val;
   val = BINDING_VALUE (binding);
-  if (namespaces_only)
+  if (LOOKUP_NAMESPACES_ONLY (flags))
     {
       /* We are not interested in types. */
       if (val && TREE_CODE (val) == NAMESPACE_DECL)
@@ -4753,10 +4753,11 @@ select_decl (binding, prefer_type, namespaces_only)
   /* If we could have a type and
      we have nothing or we need a type and have none.  */
   if (BINDING_TYPE (binding)
-      && (!val || (prefer_type && TREE_CODE (val) != TYPE_DECL)))
+      && (!val || ((flags & LOOKUP_PREFER_TYPES)
+                   && TREE_CODE (val) != TYPE_DECL)))
     val = TYPE_STUB_DECL (BINDING_TYPE (binding));
   /* Don't return non-types if we really prefer types. */
-  else if (val && prefer_type > 1  && TREE_CODE (val) != TYPE_DECL
+  else if (val && LOOKUP_TYPES_ONLY (flags)  && TREE_CODE (val) != TYPE_DECL
           && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
     val = NULL_TREE;
   return val;
@@ -4766,10 +4767,9 @@ select_decl (binding, prefer_type, namespaces_only)
    using namespace statements. */
 
 static tree
-unqualified_namespace_lookup (name, prefer_type, namespaces_only)
+unqualified_namespace_lookup (name, flags)
      tree name;
-     int prefer_type;
-     int namespaces_only;
+     int flags;
 {
   struct tree_binding _binding;
   tree b = binding_init (&_binding);
@@ -4791,7 +4791,8 @@ unqualified_namespace_lookup (name, prefer_type, namespaces_only)
       for (level = current_binding_level; 
           !level->namespace_p;
           level = level->level_chain)
-       if (!lookup_using_namespace (name, b, level->using_directives, scope))
+       if (!lookup_using_namespace (name, b, level->using_directives,
+                                     scope, flags))
          /* Give up because of error. */
          return NULL_TREE;
 
@@ -4801,14 +4802,14 @@ unqualified_namespace_lookup (name, prefer_type, namespaces_only)
       while (1)
        {
          if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), 
-                                      scope))
+                                      scope, flags))
            /* Give up because of error. */
            return NULL_TREE;
          if (siter == scope) break;
          siter = CP_DECL_CONTEXT (siter);
        }
 
-      val = select_decl (b, prefer_type, namespaces_only);
+      val = select_decl (b, flags);
       if (scope == global_namespace)
        break;
       scope = DECL_CONTEXT (scope);
@@ -4818,6 +4819,38 @@ unqualified_namespace_lookup (name, prefer_type, namespaces_only)
   return val;
 }
 
+/* Combine prefer_type and namespaces_only into flags.  */
+
+static int
+lookup_flags (prefer_type, namespaces_only)
+  int prefer_type, namespaces_only;
+{
+  if (namespaces_only)
+    return LOOKUP_PREFER_NAMESPACES;
+  if (prefer_type > 1)
+    return LOOKUP_PREFER_TYPES;
+  if (prefer_type > 0)
+    return LOOKUP_PREFER_BOTH;
+  return 0;
+}
+
+/* Given a lookup that returned VAL, use FLAGS to decide if we want to
+   ignore it or not.  Subroutine of lookup_name_real.  */
+
+static tree
+qualify_lookup (val, flags)
+     tree val;
+     int flags;
+{
+  if (val == NULL_TREE)
+    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)
+    return NULL_TREE;
+  return val;
+}
+
 /* Look up NAME in the current binding level and its superiors in the
    namespace of variables, functions and typedefs.  Return a ..._DECL
    node of some kind representing its definition if there is only one
@@ -4841,11 +4874,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
   int yylex = 0;
   tree from_obj = NULL_TREE;
   tree locval, classval;
+  int flags;
 
   /* Hack: copy flag set by parser, if set. */
   if (only_namespace_names)
     namespaces_only = 1;
-  
+
   if (prefer_type == -2)
     {
       extern int looking_for_typename;
@@ -4854,6 +4888,13 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
       yylex = 1;
       prefer_type = looking_for_typename;
 
+      flags = lookup_flags (prefer_type, namespaces_only);
+      /* During parsing, we need to complain. */
+      flags |= LOOKUP_COMPLAIN;
+      /* If the next thing is '<', class templates are types. */
+      if (looking_for_template)
+        flags |= LOOKUP_TEMPLATES_EXPECTED;
+
       /* std:: becomes :: for now.  */
       if (got_scope == std_node)
        got_scope = void_type_node;
@@ -4879,9 +4920,9 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
            {
              struct tree_binding b;
              val = binding_init (&b);
-             if (!qualified_lookup_using_namespace (name, type, val))
+             if (!qualified_lookup_using_namespace (name, type, val, flags))
                return NULL_TREE;
-             val = select_decl (val, prefer_type, namespaces_only);
+             val = select_decl (val, flags);
            }
          else if (! IS_AGGR_TYPE (type)
                   || TREE_CODE (type) == TEMPLATE_TYPE_PARM
@@ -4922,29 +4963,13 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
       else if (got_object && val)
        from_obj = val;
     }
+  else
+    flags = lookup_flags (prefer_type, namespaces_only);
 
   locval = classval = NULL_TREE;
 
-  if (!current_binding_level->namespace_p
-      && IDENTIFIER_LOCAL_VALUE (name))
-    switch (TREE_CODE (IDENTIFIER_LOCAL_VALUE (name)))
-      {
-      case NAMESPACE_DECL:
-        /* A namespace is rejected only if we strictly require types. */
-        if (prefer_type <= 1)
-          locval = IDENTIFIER_LOCAL_VALUE (name);
-        break;
-      case TYPE_DECL:
-        /* A type is rejected only if we strictly require namespaces. */
-        if (!namespaces_only)
-          locval = IDENTIFIER_LOCAL_VALUE (name);
-        break;
-      default:
-        /* We require neither types or namespaces. */
-        if (!namespaces_only && prefer_type <= 0)
-          locval = IDENTIFIER_LOCAL_VALUE (name);
-        break;
-      }
+  if (! namespace_bindings_p ())
+    locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
 
   /* In C++ class fields are between local and global scope,
      just before the global scope.  */
@@ -4972,6 +4997,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
         created the COMPONENT_REF or anything like that.  */
       if (classval == NULL_TREE)
        classval = lookup_nested_field (name, ! yylex);
+
+      classval = qualify_lookup (classval, flags);
     }
 
   if (locval && classval)
@@ -5003,7 +5030,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
   else if (classval)
     val = classval;
   else
-    val = unqualified_namespace_lookup (name, prefer_type, namespaces_only);
+    val = unqualified_namespace_lookup (name, flags);
 
  done:
   if (val)
index 2e8d569aa310269b8e44dd85713a78d31983dcd2..bd32d627dbcb6502d4622ec1fd958d38aa4c10b2 100644 (file)
@@ -60,7 +60,7 @@ 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));
+static tree ambiguous_decl PROTO((tree, tree, tree,int));
 static tree build_anon_union_vars PROTO((tree, tree*, int, int));
 static void check_decl_namespace PROTO((void));
 
@@ -3857,15 +3857,21 @@ add_using_namespace (user, used, indirect)
      tree used;
      int indirect;
 {
-  tree iter;
+  tree t;
   /* Using oneself is a no-op. */
   if (user == used)
     return;
   my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
   my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
   /* Check if we already have this. */
-  if (purpose_member (used, DECL_NAMESPACE_USING (user)) != NULL_TREE)
-    return;
+  t = purpose_member (used, DECL_NAMESPACE_USING (user));
+  if (t != NULL_TREE)
+    {
+      if (!indirect)
+       /* Promote to direct usage. */
+       TREE_INDIRECT_USING (t) = 0;
+      return;
+    }
 
   /* Add used to the user's using list. */
   DECL_NAMESPACE_USING (user) 
@@ -3879,13 +3885,13 @@ add_using_namespace (user, used, indirect)
     = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
 
   /* Recursively add all namespaces used. */
-  for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+  for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
     /* indirect usage */
-    add_using_namespace (user, TREE_PURPOSE (iter), 1);
+    add_using_namespace (user, TREE_PURPOSE (t), 1);
 
   /* Tell everyone using us about the new used namespaces. */
-  for (iter = DECL_NAMESPACE_USERS (user); iter; iter = TREE_CHAIN (iter))
-    add_using_namespace (TREE_PURPOSE (iter), used, 1);
+  for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
+    add_using_namespace (TREE_PURPOSE (t), used, 1);
 }
 
 /* Combines two sets of overloaded functions into an OVERLOAD chain.
@@ -3916,42 +3922,77 @@ merge_functions (s1, s2)
    XXX I don't want to repeat the entire duplicate_decls here */
 
 static tree
-ambiguous_decl (name, old, new)
+ambiguous_decl (name, old, new, flags)
      tree name;
      tree old;
      tree new;
+     int flags;
 {
+  tree val, type;
   my_friendly_assert (old != NULL_TREE, 393);
   /* Copy the value. */
+  val = BINDING_VALUE (new);
+  if (val)
+    switch (TREE_CODE (val))
+      {
+      case TEMPLATE_DECL:
+        /* If we expect types or namespaces, and not templates,
+           or this is not a template class. */
+        if (LOOKUP_QUALIFIERS_ONLY (flags)
+            && (!(flags & LOOKUP_TEMPLATES_EXPECTED)
+                || !DECL_CLASS_TEMPLATE_P (val)))
+          val = NULL_TREE;
+        break;
+      case TYPE_DECL:
+        if (LOOKUP_NAMESPACES_ONLY (flags))
+          val = NULL_TREE;
+        break;
+      case NAMESPACE_DECL:
+        if (LOOKUP_TYPES_ONLY (flags))
+          val = NULL_TREE;
+        break;
+      default:
+        if (LOOKUP_QUALIFIERS_ONLY (flags))
+          val = NULL_TREE;
+      }
+        
   if (!BINDING_VALUE (old))
-    BINDING_VALUE (old) = BINDING_VALUE (new);
-  else if (BINDING_VALUE (new) 
-          && BINDING_VALUE (new) != BINDING_VALUE (old))
+    BINDING_VALUE (old) = val;
+  else if (val && val != BINDING_VALUE (old))
     {
       if (is_overloaded_fn (BINDING_VALUE (old)) 
-         && is_overloaded_fn (BINDING_VALUE (new)))
+         && is_overloaded_fn (val))
        {
          BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old),
-                                                BINDING_VALUE (new));
+                                                val);
        }
       else
        {
          /* Some declarations are functions, some are not. */
-         cp_error ("use of `%D' is ambiguous", name);
-         cp_error_at ("  first declared as `%#D' here", BINDING_VALUE (old));
-         cp_error_at ("  also declared as `%#D' here", BINDING_VALUE (new));
+          if (flags & LOOKUP_COMPLAIN)
+            {
+              cp_error ("use of `%D' is ambiguous", name);
+              cp_error_at ("  first declared as `%#D' here",
+                           BINDING_VALUE (old));
+              cp_error_at ("  also declared as `%#D' here", val);
+            }
          return error_mark_node;
        }
     }
   /* ... and copy the type. */
+  type = BINDING_TYPE (new);
+  if (LOOKUP_NAMESPACES_ONLY (flags))
+    type = NULL_TREE;
   if (!BINDING_TYPE (old))
-    BINDING_TYPE (old) = BINDING_TYPE (new);
-  else if(BINDING_TYPE (new)
-         && BINDING_TYPE (old) != BINDING_TYPE (new))
+    BINDING_TYPE (old) = type;
+  else if(type && BINDING_TYPE (old) != type)
     {
-      cp_error ("`%D' denotes an ambiguous type",name);
-      cp_error_at ("first type here", BINDING_TYPE (old));
-      cp_error_at ("other type here", BINDING_TYPE (new));
+      if (flags & LOOKUP_COMPLAIN)
+        {
+          cp_error ("`%D' denotes an ambiguous type",name);
+          cp_error_at ("  first type here", BINDING_TYPE (old));
+          cp_error_at ("  other type here", type);
+        }
     }
   return old;
 }
@@ -3961,8 +4002,9 @@ ambiguous_decl (name, old, new)
    Returns zero on errors. */
 
 int
-lookup_using_namespace (name, val, usings, scope)
+lookup_using_namespace (name, val, usings, scope, flags)
      tree name, val, usings, scope;
+     int flags;
 {
   tree iter;
   tree val1;
@@ -3973,7 +4015,7 @@ lookup_using_namespace (name, val, usings, scope)
       {
        val1 = binding_for_name (name, TREE_PURPOSE (iter));
        /* Resolve ambiguities. */
-       val = ambiguous_decl (name, val, val1);
+       val = ambiguous_decl (name, val, val1, flags);
       }
   return val != error_mark_node;
 }
@@ -3984,10 +4026,11 @@ lookup_using_namespace (name, val, usings, scope)
    or 0 on error. */
 
 int
-qualified_lookup_using_namespace (name, scope, result)
+qualified_lookup_using_namespace (name, scope, result, flags)
      tree name;
      tree scope;
      tree result;
+     int flags;
 {
   /* Maintain a list of namespaces visited... */
   tree seen = NULL_TREE;
@@ -3997,7 +4040,8 @@ qualified_lookup_using_namespace (name, scope, result)
   while (scope && (result != error_mark_node))
     {
       seen = temp_tree_cons (scope, NULL_TREE, seen);
-      result = ambiguous_decl (name, result, binding_for_name (name, scope));
+      result = ambiguous_decl (name, result,
+                               binding_for_name (name, scope), flags);
       if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
        /* Consider using directives. */
        for (usings = DECL_NAMESPACE_USING (scope); usings;
@@ -4437,7 +4481,7 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
 
   *newval = *newtype = NULL_TREE;
   decls = binding_init (&_decls);
-  if (!qualified_lookup_using_namespace (name, scope, decls))
+  if (!qualified_lookup_using_namespace (name, scope, decls, 0))
     /* Lookup error */
     return;
 
index 62d061b6a44e609b155c872bdec7e37968fe492e..8573a8543fe53b1363317bd934898ec9f4fd2100 100644 (file)
@@ -3014,7 +3014,7 @@ do_scoped_id (token, parsing)
     {
       struct tree_binding _b;
       id = binding_init (&_b);
-      if (!qualified_lookup_using_namespace (token, global_namespace, id))
+      if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
        id = NULL_TREE;
       else
        id = BINDING_VALUE (id);