OSDN Git Service

* cp-tree.h (PUSH_GLOBAL): New macro.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 21 Jan 1999 21:16:22 +0000 (21:16 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 21 Jan 1999 21:16:22 +0000 (21:16 +0000)
(PUSH_LOCAL): Likewise.
(PUSH_USING): Likewise.
(namespace_bindings_p): Declare.
(push_overloaded_decl): Likewise.
* decl.c (push_overloaded_decl): Don't make it static.  Check for
illegal declarations after using declarations here.
(namespace_bindings_p): Likewise.
(duplicate_decls): Don't consider declarations from different
namespaces to be the same.
(pushdecl): Use symbolic PUSH_ constants in calls to
push_overloaded_decl.
(push_overloaded_decl_1): Likewise.
* decl2.c (validate_nonmember_using_decl): Tweak `std' handling.
(do_nonmember_using_decl): Check for illegal using declarations
after ordinary declarations here.
(do_local_using_decl): Call pushdecl to insert declarations.

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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.ns/overload4.C
gcc/testsuite/g++.old-deja/g++.ns/overload5.C
gcc/testsuite/g++.old-deja/g++.ns/using12.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/array3.C [new file with mode: 0644]

index 6db2122..280d14d 100644 (file)
@@ -1,9 +1,32 @@
+1999-01-21  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (PUSH_GLOBAL): New macro.
+       (PUSH_LOCAL): Likewise.
+       (PUSH_USING): Likewise.
+       (namespace_bindings_p): Declare.
+       (push_overloaded_decl): Likewise.
+       * decl.c (push_overloaded_decl): Don't make it static.  Check for
+       illegal declarations after using declarations here.
+       (namespace_bindings_p): Likewise.
+       (duplicate_decls): Don't consider declarations from different
+       namespaces to be the same.
+       (pushdecl): Use symbolic PUSH_ constants in calls to
+       push_overloaded_decl.
+       (push_overloaded_decl_1): Likewise.
+       * decl2.c (validate_nonmember_using_decl): Tweak `std' handling. 
+       (do_nonmember_using_decl): Check for illegal using declarations
+       after ordinary declarations here.
+       (do_local_using_decl): Call pushdecl to insert declarations.
+
 1999-01-21  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo.
 
 1999-01-21  Mark Mitchell  <mark@markmitchell.com>
 
+       * tree.c (build_cplus_array_type_1): Don't call build_array_type
+       for types involving template parameters.
+       
        * cp-tree.h (PARM_DECL_EXPR): Delete.
        (convert_default_arg): Change prototype.
        (check_default_argument): Declare.
index 7dc06ff..e26a910 100644 (file)
@@ -2582,6 +2582,14 @@ extern tree current_class_name;  /* IDENTIFIER_NODE: name of current class */
                                   another declaration of an existing
                                   entity is seen.  */
 
+/* Used with push_overloaded_decl.  */
+#define PUSH_GLOBAL          0  /* Push the DECL into namespace scope,
+                                  regardless of the current scope.  */
+#define PUSH_LOCAL           1  /* Push the DECL into the current
+                                  scope.  */
+#define PUSH_USING           2  /* We are pushing this DECL as the
+                                  result of a using declaration.  */
+
 /* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
    sense of `same'.  */
 #define same_type_p(type1, type2) \
@@ -2692,6 +2700,7 @@ extern tree perform_qualification_conversions   PROTO((tree, tree));
 extern void set_identifier_local_value         PROTO((tree, tree));
 extern int global_bindings_p                   PROTO((void));
 extern int toplevel_bindings_p                 PROTO((void));
+extern int namespace_bindings_p                        PROTO((void));
 extern void keep_next_level                    PROTO((void));
 extern int kept_level_p                                PROTO((void));
 extern void declare_parm_level                 PROTO((void));
@@ -2816,6 +2825,7 @@ extern int check_static_variable_definition     PROTO((tree, tree));
 extern void push_local_binding                  PROTO((tree, tree));
 extern void push_class_binding                  PROTO((tree, tree));
 extern tree check_default_argument              PROTO((tree, tree));
+extern tree push_overloaded_decl               PROTO((tree, int));
 
 /* in decl2.c */
 extern int check_java_method                   PROTO((tree));
index 20b5374..39e07a4 100644 (file)
@@ -135,7 +135,6 @@ static struct stack_level *decl_stack;
 static tree grokparms                          PROTO((tree, int));
 static tree lookup_nested_type                 PROTO((tree, tree));
 static char *redeclaration_error_message       PROTO((tree, tree));
-static tree push_overloaded_decl               PROTO((tree, int));
 
 static struct stack_level *push_decl_level PROTO((struct stack_level *,
                                                  struct obstack *));
@@ -145,7 +144,6 @@ static void pop_binding_level PROTO((void));
 static void suspend_binding_level PROTO((void));
 static void resume_binding_level PROTO((struct binding_level *));
 static struct binding_level *make_binding_level PROTO((void));
-static int namespace_bindings_p PROTO((void));
 static void declare_namespace_level PROTO((void));
 static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
 static void storedecls PROTO((tree));
@@ -922,7 +920,7 @@ toplevel_bindings_p ()
 
 /* Nonzero if this is a namespace scope.  */
 
-static int
+int
 namespace_bindings_p ()
 {
   return current_binding_level->namespace_p;
@@ -2942,6 +2940,11 @@ duplicate_decls (newdecl, olddecl)
     }
   else if (!types_match)
     {
+      if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
+       /* These are certainly not duplicate declarations; they're
+          from different scopes.  */
+       return 0;
+
       if (TREE_CODE (newdecl) == TEMPLATE_DECL)
        {
          /* The name of a class template may not be declared to refer to
@@ -3655,7 +3658,7 @@ pushdecl (x)
 
       if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
        {
-         t = push_overloaded_decl (x, 1);
+         t = push_overloaded_decl (x, PUSH_LOCAL);
          if (t != x || DECL_LANGUAGE (x) == lang_c)
            return t;
          if (!namespace_bindings_p ())
@@ -3665,7 +3668,7 @@ pushdecl (x)
            need_new_binding = 0;
        }
       else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
-       return push_overloaded_decl (x, 0);
+       return push_overloaded_decl (x, PUSH_GLOBAL);
 
       /* If declaring a type as a typedef, copy the type (unless we're
         at line 0), and install this TYPE_DECL as the new type's typedef
@@ -4157,19 +4160,25 @@ push_using_directive (used)
    DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
    slot.  It is dealt with the same way.
 
+   FLAGS is a bitwise-or of the following values:
+     PUSH_LOCAL: Bind DECL in the current scope, rather than at
+                 namespace scope.
+     PUSH_USING: DECL is being pushed as the result of a using
+                 declaration. 
+
    The value returned may be a previous declaration if we guessed wrong
    about what language DECL should belong to (C or C++).  Otherwise,
    it's always DECL (and never something that's not a _DECL).  */
 
-static tree
-push_overloaded_decl (decl, forgettable)
+tree
+push_overloaded_decl (decl, flags)
      tree decl;
-     int forgettable;
+     int flags;
 {
   tree name = DECL_NAME (decl);
   tree old;
   tree new_binding;
-  int doing_global = (namespace_bindings_p () || ! forgettable);
+  int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
 
   if (doing_global)
     {
@@ -4202,9 +4211,19 @@ push_overloaded_decl (decl, forgettable)
           tree tmp;
          
          for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
-           if (decl == OVL_CURRENT (tmp) 
-               || duplicate_decls (decl, OVL_CURRENT (tmp)))
-             return OVL_CURRENT (tmp);
+           {
+             tree fn = OVL_CURRENT (tmp);
+
+             if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
+                 && !(flags & PUSH_USING)
+                 && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+                               TYPE_ARG_TYPES (TREE_TYPE (decl))))
+               cp_error ("`%#D' conflicts with previous using declaration `%#D'",
+                         decl, fn);
+             
+             if (duplicate_decls (decl, fn))
+               return fn;
+           }
        }
       else
        {
@@ -5776,7 +5795,7 @@ static void
 push_overloaded_decl_1 (x)
      tree x;
 {
-  push_overloaded_decl (x, 0);
+  push_overloaded_decl (x, PUSH_GLOBAL);
 }
 
 #ifdef __GNUC__
index 3033644..ed9c11b 100644 (file)
@@ -4703,6 +4703,16 @@ validate_nonmember_using_decl (decl, scope, name)
   if (TREE_CODE (decl) == SCOPE_REF
       && TREE_OPERAND (decl, 0) == std_node)
     {
+      if (namespace_bindings_p ()
+         && current_namespace == global_namespace)
+       /* There's no need for a using declaration at all, here,
+          since `std' is the same as `::'.  We can't just pass this
+          on because we'll complain later about declaring something
+          in the same scope as a using declaration with the same
+          name.  We return NULL_TREE which indicates to the caller
+          that there's no need to do any further processing.  */
+       return NULL_TREE;
+
       *scope = global_namespace;
       *name = TREE_OPERAND (decl, 1);
     }
@@ -4773,17 +4783,37 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
       *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. */
+         tree new_fn = OVL_CURRENT (tmp);
+
+         /* [namespace.udecl]
+
+            If a function declaration in namespace scope or block
+            scope has the same name and the same parameter types as a
+            function introduced by a using declaration the program is
+            ill-formed.  */
          for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
-           if (OVL_CURRENT (tmp) == OVL_CURRENT (tmp1))
-             break;
-           else if (OVL_USED (tmp1))
-             continue;
-           else if (duplicate_decls (OVL_CURRENT (tmp), OVL_CURRENT (tmp1)))
-             return;
+           {
+             tree old_fn = OVL_CURRENT (tmp1);
 
-         /* Duplicate use, ignore */
+             if (!OVL_USED (tmp1)
+                 && compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
+                               TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+               {
+                 /* There was already a non-using declaration in
+                    this scope with the same parameter types.  */
+                 cp_error ("`%D' is already declared in this scope",
+                           name);
+                 break;
+               }
+             else if (duplicate_decls (new_fn, old_fn))
+               /* We're re-using something we already used 
+                  before.  We don't need to add it again.  */ 
+               break;
+           }
+
+         /* If we broke out of the loop, there's no reason to add
+            this function to the using declarations for this
+            scope.  */
          if (tmp1)
            continue;
            
@@ -4856,7 +4886,20 @@ do_local_using_decl (decl)
   do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
 
   if (newval)
-    push_local_binding (name, newval);
+    {
+      if (is_overloaded_fn (newval))
+       {
+         tree fn;
+
+         /* We only need to push declarations for those functions
+            that were not already bound in the current level.  */
+         for (fn = newval; fn != oldval; fn = OVL_NEXT (fn))
+           push_overloaded_decl (OVL_CURRENT (fn), 
+                                 PUSH_LOCAL | PUSH_USING);
+       }
+      else
+       push_local_binding (name, newval);
+    }
   if (newtype)
     set_identifier_type_value (name, newtype);
 }
index 65ae47a..656cc52 100644 (file)
@@ -416,7 +416,9 @@ build_cplus_array_type_1 (elt_type, index_type)
       saveable_obstack = &permanent_obstack;
     }
 
-  if (processing_template_decl)
+  if (processing_template_decl 
+      || uses_template_parms (elt_type) 
+      || uses_template_parms (index_type))
     {
       t = make_node (ARRAY_TYPE);
       TREE_TYPE (t) = elt_type;
index 24d0ced..ad96157 100644 (file)
@@ -1,6 +1,6 @@
 // Build don't link:
 namespace A{
-  void f();   // ERROR - .*
+  void f();  
 }
 
 using A::f;
index 210f3b0..24a0a6d 100644 (file)
@@ -1,6 +1,6 @@
 // Build don't link:
 namespace A{
-  void f(){}         // ERROR - previous declaration
+  void f(){}        
 }
 
 using A::f;
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/using12.C b/gcc/testsuite/g++.old-deja/g++.ns/using12.C
new file mode 100644 (file)
index 0000000..edc863b
--- /dev/null
@@ -0,0 +1,19 @@
+// Build don't link:
+// Origin: Brendan Kehoe <brendan@cygnus.com>
+
+namespace foo
+{
+  void x (bool);     // ERROR - candidates
+  void x (char);     // ERROR - candidates
+  void x (int);      // ERROR - candidates
+  void x (double);   // ERROR - candidates
+}
+
+namespace baz { void x (int); }  // ERROR - candidates
+
+void fn (int i)
+{
+  using foo::x;
+  using baz::x;
+  x(i);         // ERROR - ambiguous
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/array3.C b/gcc/testsuite/g++.old-deja/g++.pt/array3.C
new file mode 100644 (file)
index 0000000..ec5e1e0
--- /dev/null
@@ -0,0 +1,5 @@
+// Build don't link:
+// Origin: Brendan Kehoe <brendan@cygnus.com>
+
+ template <int x> int foo(char[4][x]) { return x; }
+ int (*bar)(char[4][3]) = &foo;