This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Typename Fix
- To: egcs-bugs at cygnus dot com, Jason Merrill <jason at cygnus dot com>, Mark Mitchell <mmitchell at usa dot net>
- Subject: Typename Fix
- From: Mark Mitchell <mmitchell at usa dot net>
- Date: Sat, 15 Nov 1997 17:10:11 -0800
- Reply-to: mmitchell at usa dot net
Jason --
Here's a (better) version of the fix for code like this:
template <class T>
struct A
{
typedef T A_Type;
};
template <class U>
struct B : public A<U>
{
};
template <class U>
struct C : public B<U>
{
A_Type Func();
};
template <class U>
C<U>::A_Type C<U>::Func()
{
}
which egcs-971114 fails to compile.
--
Mark Mitchell mmitchell@usa.net
Stanford University http://www.stanford.edu
Sat Nov 15 17:06:55 1997 Mark Mitchell <mmitchell@usa.net>
* cp-tree.h (lookup_field_and_base): New function.
* decl.c (lookup_name_real): Call lookup_field_and_base instead of
lookup_field.
* parse.y (nonnested_type): Lookup for inherited typedefs in
template classes.
* search.c (lookup_field): Call lookup_field_and_base.
(lookup_field_and_base): New function.
(dfs_walk): When doing pushdecls, don't recurse into template base
classes, since they might later be specialized.
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.1.1.2
diff -c -p -r1.1.1.2 cp-tree.h
*** cp-tree.h 1997/11/14 21:17:46 1.1.1.2
--- cp-tree.h 1997/11/15 00:01:01
*************** extern tree get_binfo PROTO((tree, tr
*** 2378,2383 ****
--- 2378,2384 ----
extern int get_base_distance PROTO((tree, tree, int, tree *));
extern tree compute_access PROTO((tree, tree));
extern tree lookup_field PROTO((tree, tree, int, int));
+ extern tree lookup_field_and_base PROTO((tree, tree, int, int, tree*));
extern tree lookup_nested_field PROTO((tree, int));
extern tree lookup_fnfields PROTO((tree, tree, int));
extern tree lookup_nested_tag PROTO((tree, tree));
Index: gcc/cp/decl.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl.c,v
retrieving revision 1.1.1.2
diff -c -p -r1.1.1.2 decl.c
*** decl.c 1997/11/14 21:17:46 1.1.1.2
--- decl.c 1997/11/15 20:48:15
*************** lookup_name_real (name, prefer_type, non
*** 4391,4396 ****
--- 4391,4397 ----
int yylex = 0;
tree from_obj = NULL_TREE;
tree locval, classval;
+ tree scope_type = NULL_TREE;
if (prefer_type == -2)
{
*************** lookup_name_real (name, prefer_type, non
*** 4409,4414 ****
--- 4410,4417 ----
else if (got_object != error_mark_node)
type = got_object;
+ scope_type = got_scope;
+
if (type)
{
if (type == error_mark_node)
*************** lookup_name_real (name, prefer_type, non
*** 4447,4470 ****
}
}
if (val == NULL_TREE)
! val = lookup_field (type, name, 0, 1);
}
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
! val = lookup_field (type, name, 0, prefer_type);
}
else
val = NULL_TREE;
/* Add implicit 'typename' to scoped types from other classes. */
! if (got_scope && processing_template_decl
! && got_scope != current_class_type
! && uses_template_parms (got_scope)
&& val && TREE_CODE (val) == TYPE_DECL
&& ! DECL_ARTIFICIAL (val))
{
! tree t = make_typename_type (got_scope, DECL_NAME (val));
TREE_TYPE (t) = TREE_TYPE (val);
val = TYPE_MAIN_DECL (t);
}
--- 4450,4475 ----
}
}
if (val == NULL_TREE)
! val = lookup_field_and_base (type, name, 0, 1,
! &scope_type);
}
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
! val = lookup_field_and_base (type, name, 0, prefer_type,
! &scope_type);
}
else
val = NULL_TREE;
/* Add implicit 'typename' to scoped types from other classes. */
! if (scope_type && processing_template_decl
! && scope_type != current_class_type
! && uses_template_parms (scope_type)
&& val && TREE_CODE (val) == TYPE_DECL
&& ! DECL_ARTIFICIAL (val))
{
! tree t = make_typename_type (scope_type, DECL_NAME (val));
TREE_TYPE (t) = TREE_TYPE (val);
val = TYPE_MAIN_DECL (t);
}
*************** lookup_name_real (name, prefer_type, non
*** 4486,4511 ****
if (current_class_type && ! nonclass)
{
classval = IDENTIFIER_CLASS_VALUE (name);
! if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
/* Try to find values from base classes if we are presently
defining a type. We are presently only interested in
TYPE_DECLs. */
! classval = lookup_field (current_class_type, name, 0, 1);
/* yylex() calls this with -2, since we should never start digging for
the nested name at the point where we haven't even, for example,
created the COMPONENT_REF or anything like that. */
! if (classval == NULL_TREE)
! classval = lookup_nested_field (name, ! yylex);
/* Add implicit 'typename' to types from base classes. */
if (processing_template_decl
&& classval && TREE_CODE (classval) == TYPE_DECL
! && DECL_CONTEXT (classval) != current_class_type
! && uses_template_parms (DECL_CONTEXT (classval))
&& ! DECL_ARTIFICIAL (classval))
{
! tree t = make_typename_type (DECL_CONTEXT (classval),
DECL_NAME (classval));
TREE_TYPE (t) = TREE_TYPE (classval);
classval = TYPE_MAIN_DECL (t);
--- 4491,4523 ----
if (current_class_type && ! nonclass)
{
classval = IDENTIFIER_CLASS_VALUE (name);
! if (classval == NULL_TREE
! && (TYPE_BEING_DEFINED (current_class_type)
! || uses_template_parms (current_class_type)))
/* Try to find values from base classes if we are presently
defining a type. We are presently only interested in
TYPE_DECLs. */
! classval = lookup_field_and_base (current_class_type, name, 0,
! 1, &scope_type);
/* yylex() calls this with -2, since we should never start digging for
the nested name at the point where we haven't even, for example,
created the COMPONENT_REF or anything like that. */
! if (classval == NULL_TREE)
! {
! classval = lookup_nested_field (name, ! yylex);
! if (classval != NULL_TREE)
! scope_type = DECL_CONTEXT (classval);
! }
/* Add implicit 'typename' to types from base classes. */
if (processing_template_decl
&& classval && TREE_CODE (classval) == TYPE_DECL
! && scope_type != current_class_type
! && uses_template_parms (scope_type)
&& ! DECL_ARTIFICIAL (classval))
{
! tree t = make_typename_type (scope_type,
DECL_NAME (classval));
TREE_TYPE (t) = TREE_TYPE (classval);
classval = TYPE_MAIN_DECL (t);
Index: gcc/cp/parse.y
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/parse.y,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 parse.y
*** parse.y 1997/11/08 17:53:59 1.1.1.1
--- parse.y 1997/11/15 21:05:04
*************** nonnested_type:
*** 3018,3024 ****
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
if (current_class_type
! && TYPE_BEING_DEFINED (current_class_type)
&& ! IDENTIFIER_CLASS_VALUE ($1))
{
/* Be sure to get an inherited typedef. */
--- 3018,3025 ----
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
if (current_class_type
! && (TYPE_BEING_DEFINED (current_class_type)
! || uses_template_parms (current_class_type))
&& ! IDENTIFIER_CLASS_VALUE ($1))
{
/* Be sure to get an inherited typedef. */
Index: gcc/cp/search.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/search.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 search.c
*** search.c 1997/11/08 17:53:59 1.1.1.1
--- search.c 1997/11/15 20:40:52
*************** lookup_fnfields_here (type, name)
*** 1139,1144 ****
--- 1139,1145 ----
return -1;
}
+
/* Look for a field named NAME in an inheritance lattice dominated by
XBASETYPE. PROTECT is zero if we can avoid computing access
information, otherwise it is 1. WANT_TYPE is 1 when we should only
*************** lookup_fnfields_here (type, name)
*** 1146,1157 ****
It was not clear what should happen if WANT_TYPE is set, and an
ambiguity is found. At least one use (lookup_name) to not see
! the error. */
! tree
! lookup_field (xbasetype, name, protect, want_type)
register tree xbasetype, name;
int protect, want_type;
{
int head = 0, tail = 0;
tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
--- 1147,1163 ----
It was not clear what should happen if WANT_TYPE is set, and an
ambiguity is found. At least one use (lookup_name) to not see
! the error.
! If RIMMEDIATE_BASE is non-zero, store the immediate base of
! xbasetype in which the field was found there. */
!
! tree
! lookup_field_and_base (xbasetype, name, protect, want_type,
! rimmediate_base)
register tree xbasetype, name;
int protect, want_type;
+ tree* rimmediate_base;
{
int head = 0, tail = 0;
tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
*************** lookup_field (xbasetype, name, protect,
*** 1160,1165 ****
--- 1166,1173 ----
tree entry, binfo, binfo_h;
tree own_access = access_default_node;
int vbase_name_p = VBASE_NAME_P (name);
+ tree immediate_base;
+ int depth = 0;
/* rval_binfo is the binfo associated with the found member, note,
this can be set with useful information, even when rval is not
*************** lookup_field (xbasetype, name, protect,
*** 1338,1349 ****
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
if (BINFO_FIELDS_MARKED (base_binfo) == 0)
{
tree btypes;
SET_BINFO_FIELDS_MARKED (base_binfo);
! btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
--- 1346,1362 ----
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ if (depth == 0)
+ immediate_base = TREE_TYPE (base_binfo);
+
if (BINFO_FIELDS_MARKED (base_binfo) == 0)
{
tree btypes;
SET_BINFO_FIELDS_MARKED (base_binfo);
! btypes = my_tree_cons (immediate_base, base_binfo,
! basetype_chain);
TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
*************** lookup_field (xbasetype, name, protect,
*** 1369,1374 ****
--- 1382,1388 ----
basetype_chain = search_stack->first[head++];
binfo_h = TREE_VALUE (basetype_chain);
basetype_chain = TREE_CHAIN (basetype_chain);
+ immediate_base = TREE_PURPOSE (basetype_chain);
basetype_path = TREE_VALUE (basetype_chain);
if (TREE_CHAIN (basetype_chain))
BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
*************** lookup_field (xbasetype, name, protect,
*** 1402,1407 ****
--- 1416,1423 ----
if (nval)
{
rval = nval;
+ if (rimmediate_base)
+ *rimmediate_base = immediate_base;
if (entry || protect)
this_v = compute_access (basetype_path, rval);
/* These may look ambiguous, but they really are not. */
*************** lookup_field (xbasetype, name, protect,
*** 1424,1429 ****
--- 1440,1447 ----
break;
}
}
+
+ ++depth;
}
{
tree *tp = search_stack->first;
*************** lookup_field (xbasetype, name, protect,
*** 1542,1547 ****
--- 1560,1575 ----
return rval;
}
+
+ tree
+ lookup_field (xbasetype, name, protect, want_type)
+ register tree xbasetype, name;
+ int protect, want_type;
+ {
+ return lookup_field_and_base (xbasetype, name, protect, want_type, 0);
+ }
+
+
/* Try to find NAME inside a nested class. */
tree
*************** dfs_walk (binfo, fn, qfn)
*** 2510,2515 ****
--- 2538,2551 ----
dfs_walk (base_binfo, fn, qfn);
vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
+ }
+ else if (fn == dfs_pushdecls)
+ {
+ /* We don't want to enter template base classes of template
+ classes because we will then give bindings to some names
+ that may not exist if the base class is specialized. */
+ if (!uses_template_parms (TREE_TYPE (base_binfo)))
+ dfs_walk (base_binfo, fn, qfn);
}
else
dfs_walk (base_binfo, fn, qfn);
cvs diff: Diffing gcc/cp/inc
cvs diff: Diffing gcc/ginclude
cvs diff: Diffing gcc/testsuite
cvs diff: Diffing gcc/testsuite/config
cvs diff: Diffing gcc/testsuite/g++.old-deja
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.benjamin
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.bob
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.brendan
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.bugs
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.ext
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.gb
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.jason
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.law
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.mike
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.niklas
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.other
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.pt
Index: gcc/testsuite/g++.old-deja/g++.pt/typename3.C
===================================================================
RCS file: typename3.C
diff -N typename3.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- typename3.C Sat Nov 15 16:45:35 1997
***************
*** 0 ****
--- 1,20 ----
+ // Build don't link:
+
+ template <class T>
+ struct A
+ {
+ typedef T A_Type;
+ };
+
+
+ template <class U>
+ struct B : public A<U>
+ {
+ A_Type Func();
+ };
+
+
+ template <class U>
+ A<U>::A_Type B<U>::Func()
+ {
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/typename4.C
===================================================================
RCS file: typename4.C
diff -N typename4.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- typename4.C Sat Nov 15 16:45:44 1997
***************
*** 0 ****
--- 1,26 ----
+ // Build don't link:
+
+ template <class T>
+ struct A
+ {
+ typedef T A_Type;
+ };
+
+
+ template <class U>
+ struct B : public A<U>
+ {
+ };
+
+
+ template <class U>
+ struct C : public B<U>
+ {
+ A_Type Func();
+ };
+
+
+ template <class U>
+ C<U>::A_Type C<U>::Func()
+ {
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/typename5.C
===================================================================
RCS file: typename5.C
diff -N typename5.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- typename5.C Sat Nov 15 16:45:50 1997
***************
*** 0 ****
--- 1,26 ----
+ // Build don't link:
+
+ template <class T>
+ struct A
+ {
+ typedef T A_Type;
+ };
+
+
+ template <class U>
+ struct B : public A<U>
+ {
+ };
+
+
+ template <class U>
+ struct C : public B<U>
+ {
+ void Func(A_Type);
+ };
+
+
+ template <class U>
+ void C<U>::Func(A_Type)
+ {
+ }