aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-08-02 18:52:16 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-08-02 18:52:16 +0000
commitfd9aef9d180a377a8804a40a89284956f36f0016 (patch)
tree81299072d7ee64d2599788c3e47f00daaea546e5 /gcc
parent49634b3a45f7d9e65a521ac665014d6a81194dc4 (diff)
downloadgcc-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/ChangeLog14
-rw-r--r--gcc/cp/class.c16
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/decl2.c38
-rw-r--r--gcc/cp/pt.c8
-rw-r--r--gcc/cp/semantics.c3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/using7.C21
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;
+}