]> gcc.gnu.org Git - gcc.git/commitdiff
re PR c++/9447 (using Base<T>::member does not work)
authorNathan Sidwell <nathan@codesourcery.com>
Tue, 29 Jul 2003 11:16:50 +0000 (11:16 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 29 Jul 2003 11:16:50 +0000 (11:16 +0000)
cp:
PR c++/9447
* decl.c (add_binding): Add bval local variable.
(push_class_level_binding): Likewise. Allow a USING_DECL to be
pushed.
* decl2.c (do_class_using_decl):  The type of a using decl is
unknown.
* parser.c (cp_parser_postfix_expression): Refactor unqualified-id
function call lookup code.
* pt.c (tsubst): A USING_DECL will have unknown type.
(tsubst_copy_and_build): Allow a using decl.
(type_dependent_expression_p): A USING_DECL will make it
dependent.
* semantics.c (finish_member_declaration): Push a dependent using
declaration.
testsuite:
PR c++/9447
* g++.dg/template/using1.C: New test.
* g++.dg/template/using2.C: New test.
* g++.dg/template/using3.C: New test.
* g++.dg/template/using4.C: New test.

From-SVN: r69921

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/using1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/using2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/using3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/using4.C [new file with mode: 0644]

index 583d13ff584cc684f0c6e726a0eea1e6c0f29669..12d843583f1fd824cefd1100ebc1caa36a55438c 100644 (file)
@@ -1,3 +1,20 @@
+2003-07-29  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9447
+       * decl.c (add_binding): Add bval local variable.
+       (push_class_level_binding): Likewise. Allow a USING_DECL to be
+       pushed.
+       * decl2.c (do_class_using_decl):  The type of a using decl is
+       unknown.
+       * parser.c (cp_parser_postfix_expression): Refactor unqualified-id
+       function call lookup code.
+       * pt.c (tsubst): A USING_DECL will have unknown type.
+       (tsubst_copy_and_build): Allow a using decl.
+       (type_dependent_expression_p): A USING_DECL will make it
+       dependent.
+       * semantics.c (finish_member_declaration): Push a dependent using
+       declaration.
+
 2003-07-28  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/11530
index 583b87417443c45b0a52e98b237254fbba320e4a..637ad1f36d5fcb7a11b2dfce3789cdfce9a4f1fc 100644 (file)
@@ -922,38 +922,37 @@ static int
 add_binding (tree id, tree decl)
 {
   cxx_binding *binding = IDENTIFIER_BINDING (id);
+  tree bval = BINDING_VALUE (binding);
   int ok = 1;
 
   timevar_push (TV_NAME_LOOKUP);
   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
     /* The new name is the type name.  */
     BINDING_TYPE (binding) = decl;
-  else if (!BINDING_VALUE (binding))
+  else if (!bval)
     /* This situation arises when push_class_level_binding moves an
        inherited type-binding out of the way to make room for a new
        value binding.  */
     BINDING_VALUE (binding) = decl;
-  else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
-          && DECL_ARTIFICIAL (BINDING_VALUE (binding)))
+  else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval))
     {
       /* The old binding was a type name.  It was placed in
         BINDING_VALUE because it was thought, at the point it was
         declared, to be the only entity with such a name.  Move the
         type name into the type slot; it is now hidden by the new
         binding.  */
-      BINDING_TYPE (binding) = BINDING_VALUE (binding);
+      BINDING_TYPE (binding) = bval;
       BINDING_VALUE (binding) = decl;
       INHERITED_VALUE_BINDING_P (binding) = 0;
     }
-  else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+  else if (TREE_CODE (bval) == TYPE_DECL
           && TREE_CODE (decl) == TYPE_DECL
-          && DECL_NAME (decl) == DECL_NAME (BINDING_VALUE (binding))
-          && (same_type_p (TREE_TYPE (decl),
-                           TREE_TYPE (BINDING_VALUE (binding)))
+          && DECL_NAME (decl) == DECL_NAME (bval)
+          && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
               /* If either type involves template parameters, we must
                  wait until instantiation.  */
               || uses_template_parms (TREE_TYPE (decl))
-              || uses_template_parms (TREE_TYPE (BINDING_VALUE (binding)))))
+              || uses_template_parms (TREE_TYPE (bval))))
     /* We have two typedef-names, both naming the same type to have
        the same name.  This is OK because of:
 
@@ -971,10 +970,8 @@ add_binding (tree id, tree decl)
 
        A member shall not be declared twice in the
        member-specification.  */
-  else if (TREE_CODE (decl) == VAR_DECL
-          && TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
-          && DECL_EXTERNAL (decl)
-          && DECL_EXTERNAL (BINDING_VALUE (binding))
+  else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (bval) == VAR_DECL
+          && DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
           && !DECL_CLASS_SCOPE_P (decl))
     {
       duplicate_decls (decl, BINDING_VALUE (binding));
@@ -4273,47 +4270,54 @@ push_class_level_binding (tree name, tree x)
      class, then we will need to restore IDENTIFIER_CLASS_VALUE when
      we leave this class.  Record the shadowed declaration here.  */
   binding = IDENTIFIER_BINDING (name);
-  if (binding
-      && ((TREE_CODE (x) == OVERLOAD
-          && BINDING_VALUE (binding)
-          && is_overloaded_fn (BINDING_VALUE (binding)))
-         || INHERITED_VALUE_BINDING_P (binding)))
+  if (binding && BINDING_VALUE (binding))
     {
-      tree shadow;
-      tree old_decl;
+      tree bval = BINDING_VALUE (binding);
+      tree old_decl = NULL_TREE;
 
-      /* If the old binding was from a base class, and was for a tag
-        name, slide it over to make room for the new binding.  The
-        old binding is still visible if explicitly qualified with a
-        class-key.  */
-      if (INHERITED_VALUE_BINDING_P (binding)
-         && BINDING_VALUE (binding)
-         && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
-         && DECL_ARTIFICIAL (BINDING_VALUE (binding))
-         && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
-       {
-         old_decl = BINDING_TYPE (binding);
-         BINDING_TYPE (binding) = BINDING_VALUE (binding);
-         BINDING_VALUE (binding) = NULL_TREE;
-         INHERITED_VALUE_BINDING_P (binding) = 0;
+      if (INHERITED_VALUE_BINDING_P (binding))
+       {
+         /* If the old binding was from a base class, and was for a
+            tag name, slide it over to make room for the new binding.
+            The old binding is still visible if explicitly qualified
+            with a class-key.  */
+         if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
+             && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+           {
+             BINDING_TYPE (binding) = bval;
+             BINDING_VALUE (binding) = NULL_TREE;
+             INHERITED_VALUE_BINDING_P (binding) = 0;
+           }
+         old_decl = bval;
+       }
+      else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
+       old_decl = bval;
+      else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL)
+       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+      else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval))
+       old_decl = bval;
+      else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x))
+       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+      
+      if (old_decl)
+       {
+         tree shadow;
+         
+         /* Find the previous binding of name on the class-shadowed
+             list, and update it.  */
+         for (shadow = class_binding_level->class_shadowed;
+              shadow;
+              shadow = TREE_CHAIN (shadow))
+           if (TREE_PURPOSE (shadow) == name
+               && TREE_TYPE (shadow) == old_decl)
+             {
+               BINDING_VALUE (binding) = x;
+               INHERITED_VALUE_BINDING_P (binding) = 0;
+               TREE_TYPE (shadow) = x;
+               IDENTIFIER_CLASS_VALUE (name) = x;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+             }
        }
-      else
-       old_decl = BINDING_VALUE (binding);
-
-      /* Find the previous binding of name on the class-shadowed
-         list, and update it.  */
-      for (shadow = class_binding_level->class_shadowed;
-          shadow;
-          shadow = TREE_CHAIN (shadow))
-       if (TREE_PURPOSE (shadow) == name
-           && TREE_TYPE (shadow) == old_decl)
-         {
-           BINDING_VALUE (binding) = x;
-           INHERITED_VALUE_BINDING_P (binding) = 0;
-           TREE_TYPE (shadow) = x;
-           IDENTIFIER_CLASS_VALUE (name) = x;
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
-         }
     }
 
   /* If we didn't replace an existing binding, put the binding on the
index 4a6e78d500f184c7b96ac6fc7caf7fbd5787ba99..896282c770d2bbb92bb58514abebe33245b77123 100644 (file)
@@ -4126,7 +4126,7 @@ do_class_using_decl (tree decl)
 
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
 
-  value = build_lang_decl (USING_DECL, name, void_type_node);
+  value = build_lang_decl (USING_DECL, name, unknown_type_node);
   DECL_INITIAL (value) = TREE_OPERAND (decl, 0);
   return value;
 }
index 00f1c6eda4fe3a2d7ff14aa6a56cfd46b968dfa6..3aa684b3d2c56a604912a193f9b3090347f1a42c 100644 (file)
@@ -3483,18 +3483,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                parser->non_constant_expression_p = true;
              }
 
-           if (idk == CP_ID_KIND_UNQUALIFIED
-               && (is_overloaded_fn (postfix_expression)
-                   || DECL_P (postfix_expression)
-                   || TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
-               && args)
-             postfix_expression 
-               = perform_koenig_lookup (postfix_expression, args);
-           else if (idk == CP_ID_KIND_UNQUALIFIED 
-                    && TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
-             postfix_expression
-               = unqualified_fn_lookup_error (postfix_expression);
-
+           if (idk == CP_ID_KIND_UNQUALIFIED)
+             {
+               if (args
+                   && (is_overloaded_fn (postfix_expression)
+                       || DECL_P (postfix_expression)
+                       || TREE_CODE (postfix_expression) == IDENTIFIER_NODE))
+                 postfix_expression 
+                   = perform_koenig_lookup (postfix_expression, args);
+               else if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
+                 postfix_expression
+                   = unqualified_fn_lookup_error (postfix_expression);
+             }
+         
            if (TREE_CODE (postfix_expression) == COMPONENT_REF)
              {
                tree instance = TREE_OPERAND (postfix_expression, 0);
index 8f10de49065d5775737794714509c205fb5dc9a9..6966afdc8f5ebde2acbe1c70a87b6141987047e6 100644 (file)
@@ -6430,14 +6430,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     type = IDENTIFIER_TYPE_VALUE (t);
   else
     type = TREE_TYPE (t);
-  if (type == unknown_type_node)
-    abort ();
+
+  my_friendly_assert (type != unknown_type_node
+                     || TREE_CODE (t) == USING_DECL, 20030716);
 
   if (type && TREE_CODE (t) != FUNCTION_DECL
       && TREE_CODE (t) != TYPENAME_TYPE
       && TREE_CODE (t) != TEMPLATE_DECL
       && TREE_CODE (t) != IDENTIFIER_NODE
       && TREE_CODE (t) != FUNCTION_TYPE
+      && TREE_CODE (t) != USING_DECL
       && TREE_CODE (t) != METHOD_TYPE)
     type = tsubst (type, args, complain, in_decl);
   if (type == error_mark_node)
@@ -7907,6 +7909,9 @@ tsubst_copy_and_build (tree t,
 
   switch (TREE_CODE (t))
     {
+    case USING_DECL:
+      t = DECL_NAME (t);
+      /* Fallthrough. */
     case IDENTIFIER_NODE:
       {
        tree decl;
@@ -11618,6 +11623,8 @@ type_dependent_expression_p (tree expression)
 
   if (TREE_TYPE (expression) == unknown_type_node)
     {
+      if (TREE_CODE (expression) == USING_DECL)
+       return true;
       if (TREE_CODE (expression) == ADDR_EXPR)
        return type_dependent_expression_p (TREE_OPERAND (expression, 0));
       if (TREE_CODE (expression) == BASELINK)
index bf30ca08b8f1045e91ef9751eaed9e0f8e009fa8..a94174ad945b433aaddb48af7eecac836fc25f97 100644 (file)
@@ -2030,7 +2030,9 @@ finish_member_declaration (tree decl)
                                          /*friend_p=*/0);
     }
   /* Enter the DECL into the scope of the class.  */
-  else if (TREE_CODE (decl) == USING_DECL || pushdecl_class_level (decl))
+  else if ((TREE_CODE (decl) == USING_DECL && !processing_template_decl
+           && !dependent_type_p (DECL_INITIAL (decl)))
+          || pushdecl_class_level (decl))
     {
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
         go at the beginning.  The reason is that lookup_field_1
index b17dee5e091509acc7d2be6ca8021a2f5a57cb5c..520d8d0c2a7313e7612b06ca9a42d3eb51a3fea1 100644 (file)
@@ -1,3 +1,11 @@
+2003-07-29  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9447
+       * g++.dg/template/using1.C: New test.
+       * g++.dg/template/using2.C: New test.
+       * g++.dg/template/using3.C: New test.
+       * g++.dg/template/using4.C: New test.
+
 2003-07-29  Alexandre Oliva  <aoliva@redhat.com>
 
        * gcc.c-torture/execute/string-opt-9.c: strcmp returns int.
diff --git a/gcc/testsuite/g++.dg/template/using1.C b/gcc/testsuite/g++.dg/template/using1.C
new file mode 100644 (file)
index 0000000..e4d4a00
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-do run }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 22 Jul 2003 <nathan@codesourcery.com>
+
+// PR 9447. Using decls in template classes.
+
+template <class T>
+struct Foo {
+  int i;
+};
+
+struct Baz 
+{
+  int j;
+};
+
+template <class T>
+struct Bar : public Foo<T>, Baz {
+  using Foo<T>::i;
+  using Baz::j;
+  
+  int foo () { return i; }
+  int baz () { return j; }
+};
+
+int main()
+{
+  Bar<int> bar;
+
+  bar.i = 1;
+  bar.j = 2;
+  
+  if (bar.foo() != 1)
+    return 1;
+  
+  if (bar.baz() != 2)
+    return 1;
+  
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/template/using2.C b/gcc/testsuite/g++.dg/template/using2.C
new file mode 100644 (file)
index 0000000..87cdbc1
--- /dev/null
@@ -0,0 +1,30 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 22 Jul 2003 <nathan@codesourcery.com>
+
+// PR 9447. Using decls in template classes.
+
+template <class T>
+struct Foo {
+  int i; // { dg-error "" "" }
+};
+
+struct Baz 
+{
+  int i; // { dg-error "" "" }
+};
+
+template <class T>
+struct Bar : public Foo<T>, Baz {
+  using Foo<T>::i;
+  using Baz::i;
+
+  int foo () { return i; } // { dg-error "request for member" "" }
+};
+
+void foo (Bar<int> &bar)
+{
+  bar.foo(); // { dg-error "instantiated" "" }
+}
+
diff --git a/gcc/testsuite/g++.dg/template/using3.C b/gcc/testsuite/g++.dg/template/using3.C
new file mode 100644 (file)
index 0000000..11f2899
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-do run }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 22 Jul 2003 <nathan@codesourcery.com>
+
+// PR 9447. Using decls in template classes.
+
+template <class T>
+struct Foo {
+  int i (int) {return 1;}
+};
+
+struct Baz 
+{
+  int k (int) {return 2;}
+};
+
+template <class T>
+struct Bar : public Foo<T> , Baz {
+  using Foo<T>::i;
+  using Baz::k;
+
+  int i (float) {return 3;}
+  int k (float) {return 3;}
+  
+  int foo()
+  {
+    if (i (1) != 1)
+      return 1;
+    if (k (1) != 2)
+      return 2;
+
+    return 0;
+  }
+};
+
+int main()
+{
+  Bar<int> bar;
+
+  return bar.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/using4.C b/gcc/testsuite/g++.dg/template/using4.C
new file mode 100644 (file)
index 0000000..8c46da4
--- /dev/null
@@ -0,0 +1,39 @@
+// { dg-do run }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 22 Jul 2003 <nathan@codesourcery.com>
+
+// PR 9447. Using decls in template classes.
+
+template <class T>
+struct Foo {
+  int k (float) {return 1;}
+};
+
+struct Baz 
+{
+  int k (int) {return 2;}
+};
+
+template <class T>
+struct Bar : public Foo<T> , Baz {
+  using Foo<T>::k;
+  using Baz::k;
+
+  int foo()
+  {
+    if (k (1.0f) != 1)
+      return 1;
+    if (k (1) != 2)
+      return 2;
+
+    return 0;
+  }
+};
+
+int main()
+{
+  Bar<int> bar;
+
+  return bar.foo();
+}
This page took 0.136101 seconds and 5 git commands to generate.