diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2003-08-02 18:52:16 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2003-08-02 18:52:16 +0000 |
commit | fd9aef9d180a377a8804a40a89284956f36f0016 (patch) | |
tree | 81299072d7ee64d2599788c3e47f00daaea546e5 /gcc | |
parent | 49634b3a45f7d9e65a521ac665014d6a81194dc4 (diff) | |
download | gcc-fd9aef9d180a377a8804a40a89284956f36f0016.zip gcc-fd9aef9d180a377a8804a40a89284956f36f0016.tar.gz gcc-fd9aef9d180a377a8804a40a89284956f36f0016.tar.bz2 |
re PR c++/9447 (using Base<T>::member does not work)
cp:
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.
testsuite:
PR c++/9447
* g++.dg/template/using7.C: New test.
From-SVN: r70107
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/class.c | 16 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 38 | ||||
-rw-r--r-- | gcc/cp/pt.c | 8 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/using7.C | 21 |
9 files changed, 80 insertions, 32 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4a5f939..de0923a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,19 @@ 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. * class.c (pushclass): Remove unneeded MODIFY parm. Adjust. (push_nested_class): Adjust pushclass call. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a85b112..bf16721 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 5e853fe..f020a23 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 593dced..ab6913c 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 6f06860..8ec34b2 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 35c1367..185a203 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 11f5ff0..0931e89 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 9b982ee..93da359 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 0000000..390dfba --- /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; +} |