summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/decl.c40
2 files changed, 42 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c7d567addd..f8862c0644a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
Fri Mar 20 10:42:07 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (make_implicit_typename): Rewrite removed code.
+ (make_typename_type): Call it if the type we look up comes from
+ a base that uses template parms.
+
* pt.c (complete_template_args): Rewrite.
(tsubst, FUNCTION_DECL): Use it.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 98ffff9d70f..434d84c3cdc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -179,6 +179,7 @@ static void record_builtin_type PROTO((enum rid, char *, tree));
static int member_function_or_else PROTO((tree, tree, char *));
static void bad_specifiers PROTO((tree, char *, int, int, int, int,
int));
+static tree make_implicit_typename PROTO((tree, tree));
/* a node which has tree code ERROR_MARK, and whose type is itself.
All erroneous expressions are replaced with this node. All functions
@@ -4553,6 +4554,15 @@ make_typename_type (context, name)
cp_error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
+
+ /* If this is really from a base that uses template parms,
+ push the TYPENAME_TYPE down. */
+ if (processing_template_decl
+ && context == current_class_type
+ && DECL_CONTEXT (t) != context
+ && uses_template_parms (DECL_CONTEXT (t)))
+ return make_implicit_typename (context, t);
+
return TREE_TYPE (t);
}
}
@@ -4575,7 +4585,8 @@ make_typename_type (context, name)
}
/* Given a TYPE_DECL T looked up in CONTEXT, return a TYPENAME_TYPE
- where the scope is CONTEXT. Also remember what type T refers to.
+ where the scope is the first class along the inheritance chain to T
+ that is not current_class_type.
Called from lookup_name_real to implement the implicit typename
extension. */
@@ -4584,7 +4595,32 @@ static tree
make_implicit_typename (context, t)
tree context, t;
{
- tree retval = make_typename_type (context, DECL_NAME (t));
+ tree retval;
+
+ if (context == current_class_type)
+ {
+ tree binfos = TYPE_BINFO_BASETYPES (context);
+ int n_baselinks = TREE_VEC_LENGTH (binfos);
+ int i;
+
+ /* We can't use DECL_CONTEXT (t) to help us here, because it refers
+ to the uninstantiated template type that t comes from, which is
+ probably not a base of ours. This happens because we don't
+ actually do partial instantiation of types in
+ instantiate_class_template. */
+
+ for (i = 0; i < n_baselinks; ++i)
+ {
+ tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
+ if (lookup_field (basetype, DECL_NAME (t), 0, 1))
+ {
+ context = basetype;
+ break;
+ }
+ }
+ }
+
+ retval = make_typename_type (context, DECL_NAME (t));
if (TREE_CODE (retval) == TYPENAME_TYPE)
TREE_TYPE (retval) = TREE_TYPE (t);