aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c32
-rw-r--r--gcc/cp/pt.c13
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/ns18.C30
5 files changed, 80 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f0b989c..7623f18 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,6 +1,12 @@
1999-05-22 Mark Mitchell <mark@codesourcery.com>
- * tree.c (mapcar): Handle LVALUE_EXPR.
+ * cp-tree.h (push_nested_namespace): Declare.
+ (pop_nested_namespace): Likewise.
+ * decl.c (push_nested_namespace): New function.
+ (pop_nested_namespace): Likewise.
+ * pt.c (instantiate_class_template): Use them.
+
+ * tree.c (mapcar): Handle NON_LVALUE_EXPR.
* cp-tree.h (cplus_expand_constant): Declare.
* cvt.c (convert_to_pointer): Expand PTRMEM_CSTs when they're
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ec5ef45..a482824 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2781,6 +2781,8 @@ extern void print_binding_stack PROTO((void));
extern void print_binding_level PROTO((struct binding_level *));
extern void push_namespace PROTO((tree));
extern void pop_namespace PROTO((void));
+extern void push_nested_namespace PROTO((tree));
+extern void pop_nested_namespace PROTO((tree));
extern void maybe_push_to_top_level PROTO((int));
extern void push_to_top_level PROTO((void));
extern void pop_from_top_level PROTO((void));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index dd2dbb7..2308e4c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2396,6 +2396,38 @@ pop_namespace ()
suspend_binding_level ();
}
+/* Push into the scope of the namespace NS, even if it is deeply
+ nested within another namespace. */
+
+void
+push_nested_namespace (ns)
+ tree ns;
+{
+ if (ns == global_namespace)
+ push_to_top_level ();
+ else
+ {
+ push_nested_namespace (CP_DECL_CONTEXT (ns));
+ push_namespace (DECL_NAME (ns));
+ }
+}
+
+/* Pop back from the scope of the namespace NS, which was previously
+ entered with push_nested_namespace. */
+
+void
+pop_nested_namespace (ns)
+ tree ns;
+{
+ while (ns != global_namespace)
+ {
+ pop_namespace ();
+ ns = CP_DECL_CONTEXT (ns);
+ }
+
+ pop_from_top_level ();
+}
+
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6db901c..8c80173 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5079,11 +5079,16 @@ instantiate_class_template (type)
new_friend_type = tsubst (friend_type, args, /*complain=*/1,
NULL_TREE);
else
- /* The call to xref_tag_from_type does injection for friend
- classes. */
- new_friend_type =
- xref_tag_from_type (friend_type, NULL_TREE, 1);
+ {
+ tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
+ /* The call to xref_tag_from_type does injection for friend
+ classes. */
+ push_nested_namespace (ns);
+ new_friend_type =
+ xref_tag_from_type (friend_type, NULL_TREE, 1);
+ pop_nested_namespace (ns);
+ }
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
/* Trick make_friend_class into realizing that the friend
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/ns18.C b/gcc/testsuite/g++.old-deja/g++.ns/ns18.C
new file mode 100644
index 0000000..445ef6b
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.ns/ns18.C
@@ -0,0 +1,30 @@
+// Build don't link:
+// Origin: Theo Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
+
+namespace Bname {
+ class B;
+}
+
+template <class T>
+class A {
+ friend class Bname::B;
+ static const int a = 1;
+public:
+ A() { }
+};
+
+namespace Bname {
+ class B {
+ int a;
+ public:
+ template<class T>
+ B(const T&):a(T::a) { }
+ };
+}
+
+int
+main()
+{
+ A<int> a;
+ Bname::B b(a);
+}