diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4a5f939491720aba4e9f3e2a664f75221892e784..de0923a96cf14b4bcfb8095932b7837a3f9877a8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2003-08-02 Nathan Sidwell <nathan@codesourcery.com> + + PR c++/9447 + * cp-tree.def (USING_DECL): Document its type. + * class.c (pushclass): If we're entering a template, push any + dependent using decls it has. + * decl2.c (do_class_using_decl): Refactor. Type is NULL iff it is + a dependent scope. + * pt.c (tsubst_decl) <USING_DECL case>: Set type. + (tsubst): Remove USING_DECL checks. + (type_dependent_expression_p): Remove USING_DECL case. + * semantics.c (finish_member_declaration): A USING_DECL's type + indicates whether it is dependent. + 2003-08-02 Nathan Sidwell <nathan@codesourcery.com> * cp-tree.h (pushclass): Remove unneeded parameter. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a85b11274c8dddfc504dd4c192859741bd3068cf..bf1672127bfd9f22ff713825487cb844f07bbf53 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5457,7 +5457,21 @@ pushclass (tree type) pushlevel_class (); if (type != previous_class_type || current_class_depth > 1) - push_class_decls (type); + { + push_class_decls (type); + if (CLASSTYPE_IS_TEMPLATE (type)) + { + /* If we are entering the scope of a template (not a + specialization), we need to push all the using decls with + dependent scope too. */ + tree fields; + + for (fields = TYPE_FIELDS (type); + fields; fields = TREE_CHAIN (fields)) + if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields)) + pushdecl_class_level (fields); + } + } else { tree item; diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 5e853fea085799271e490b3a02f2a0f35d4e9bb3..f020a23d6a2f65e68c57d3f1fbf69dd4be943b0c 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -195,7 +195,9 @@ DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", 't', 0) DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0) /* A using declaration. DECL_INITIAL contains the specified scope. - This is not an alias, but is later expanded into multiple aliases. */ + This is not an alias, but is later expanded into multiple aliases. + The decl will have a NULL_TYPE iff the scope is a dependent scope, + otherwise it will have a void type. */ DEFTREECODE (USING_DECL, "using_decl", 'd', 0) /* A using directive. The operand is USING_STMT_NAMESPACE. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 593dcede6e6ba4d89cad3444dfd10844d4124bb4..ab6913cc0c81ae584645612d49b7a6e7d70417bc 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -11632,7 +11632,8 @@ grokdeclarator (tree declarator, inlinep, friendp, raises != NULL_TREE); } } - else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) + else if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) { tree original_name; int publicp = 0; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 6f0686069e13d5db7a18cf127ab47d1fea3c1bcd..8ec34b2e03e5292f3e1e1b89fc9eb1ce8b5520f7 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4045,8 +4045,8 @@ do_local_using_decl (tree decl) tree do_class_using_decl (tree decl) { - tree name, value; - + tree name, value, scope, type; + if (TREE_CODE (decl) != SCOPE_REF || !TREE_OPERAND (decl, 0) || !TYPE_P (TREE_OPERAND (decl, 0))) @@ -4054,50 +4054,44 @@ do_class_using_decl (tree decl) error ("using-declaration for non-member at class scope"); return NULL_TREE; } + scope = TREE_OPERAND (decl, 0); name = TREE_OPERAND (decl, 1); if (TREE_CODE (name) == BIT_NOT_EXPR) { - error ("using-declaration for destructor"); + error ("using-declaration cannot name destructor"); return NULL_TREE; } else if (TREE_CODE (name) == TEMPLATE_ID_EXPR) { - name = TREE_OPERAND (name, 0); - error ("a using-declaration cannot specify a template-id. Try `using %T::%D'", TREE_OPERAND (decl, 0), name); + template_id_error:; + + error ("a using-declaration cannot specify a template-id"); return NULL_TREE; } if (TREE_CODE (name) == TYPE_DECL) { - tree type = TREE_TYPE (name); if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name))) - { - name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)); - error ("a using-declaration cannot specify a template-id."); - return NULL_TREE; - } + goto template_id_error; name = DECL_NAME (name); } else if (TREE_CODE (name) == TEMPLATE_DECL) name = DECL_NAME (name); else if (BASELINK_P (name)) { - tree fns; - - fns = BASELINK_FUNCTIONS (name); + tree fns = BASELINK_FUNCTIONS (name); + if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) - { - fns = TREE_OPERAND (fns, 0); - error ("a using-declaration cannot specify a template-id. Try `using %T::%D'", - BASELINK_ACCESS_BINFO (name), - DECL_NAME (get_first_fn (fns))); - } + goto template_id_error; name = DECL_NAME (get_first_fn (fns)); } my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716); - value = build_lang_decl (USING_DECL, name, NULL_TREE); - DECL_INITIAL (value) = TREE_OPERAND (decl, 0); + /* Dependent using decls have a NULL type, non-dependent ones have a + void type. */ + type = dependent_type_p (scope) ? NULL_TREE : void_type_node; + value = build_lang_decl (USING_DECL, name, type); + DECL_INITIAL (value) = scope; return value; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 35c13670c7c20dff5722b95a0cae157bdd8f7b0f..185a203c20024cd29d067cb10d2ec8103e972b04 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6093,6 +6093,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) case USING_DECL: { r = copy_node (t); + /* It is not a dependent using decl any more. */ + TREE_TYPE (r) = void_type_node; DECL_INITIAL (r) = tsubst_copy (DECL_INITIAL (t), args, complain, in_decl); TREE_CHAIN (r) = NULL_TREE; @@ -6403,15 +6405,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else type = TREE_TYPE (t); - my_friendly_assert (type != unknown_type_node - || TREE_CODE (t) == USING_DECL, 20030716); + my_friendly_assert (type != unknown_type_node, 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) @@ -11623,8 +11623,6 @@ 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) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 11f5ff045d3bd478ee0f2db23bdab8f853fa5317..0931e891e048bc13fcc8eba3b2af053fcfa5233d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2099,8 +2099,7 @@ finish_member_declaration (tree decl) /*friend_p=*/0); } /* Enter the DECL into the scope of the class. */ - else if ((TREE_CODE (decl) == USING_DECL && !processing_template_decl - && !dependent_type_p (DECL_INITIAL (decl))) + else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl)) || pushdecl_class_level (decl)) { /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9b982ee16b291c66f58b228d5dcc9662d5e506e5..93da3595af9078562e95f49a2d74cb1f712a6702 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-08-02 Nathan Sidwell <nathan@codesourcery.com> + + PR c++/9447 + * g++.dg/template/using7.C: New test. + 2003-08-02 Neil Booth <neil@daikokuya.co.uk> * import1.c, import2.c: New tests. diff --git a/gcc/testsuite/g++.dg/template/using7.C b/gcc/testsuite/g++.dg/template/using7.C new file mode 100644 index 0000000000000000000000000000000000000000..390dfbaace9d185fd5bf7d7e50a6662b39571bfa --- /dev/null +++ b/gcc/testsuite/g++.dg/template/using7.C @@ -0,0 +1,21 @@ +// { dg-do compile } + +// Copyright (C) 2003 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 1 Aug 2003 <nathan@codesourcery.com> + +// PR 9447. Using decls in reopened template classes. + +template <typename> struct A { int i; }; + +template <typename T> struct B : public A<T> +{ + using A<T>::i; + int foo() const; +}; + +struct C {}; + +template <typename T> int B<T>::foo() const +{ + return i; +}