[C++ PATCH for 3.1] Fix PR6716 regression (take 4)
Kriang Lerdsuwanakij
lerdsuwa@users.sourceforge.net
Sat Jun 29 08:26:00 GMT 2002
Hi
This should be the final version of fix for PR6716. Only valid
fields are added to TYPE_FIELDS of the type to be instantiated.
However we have to instantiate these valid fields after TYPE_FIELDS
and TYPE_METHODS are completely filled. Following is an example
(from g++.dg/template/friend.C testcase):
template<class T> void f(typename C<T>::X &); //#1
template<class T> struct C {
class X {
friend void f(typename C<T>::X &); //#2
...
};
X x;
...
};
When instantiating X inside C<int>, we process the friend function #2.
There we have to do name lookup for typename C<T>::X (with T=int) at #1
to decide whether #1 is right the function #2 actually refers to.
So all field of C<int> have to be set up before we try to complete
its field x.
The logic to decide if the field can be added to TYPE_FIELDS is in
the new function, can_complete_type. We detect invalid field by
looking for TYPE_BEING_DEFINED != 0.
The changes in typeck2.c fix the generated error message. Incomplete
types coming from templates are not necessary forward declarations.
Bootstrapped and tested with no regressions. Ok to commit to 3.1
branch and mainline?
--Kriang
2002-06-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/6716
* typeck.c (can_complete_type): New function.
* cp-tree.h (can_complete_type): Add declaration.
* pt.c (instantiate_class_template): Don't add invalid fields
to TYPE_FIELDS.
* typeck2.c (incomplete_type_error): Improve error message
due to incomplete fields.
2002-06-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.dg/template/instantiate1.C: New test.
diff -cprN gcc-31-save/gcc/cp/cp-tree.h gcc-31-new/gcc/cp/cp-tree.h
*** gcc-31-save/gcc/cp/cp-tree.h Sun May 26 21:14:16 2002
--- gcc-31-new/gcc/cp/cp-tree.h Sat Jun 29 19:20:19 2002
*************** extern tree cp_truthvalue_conversion PA
*** 4297,4302 ****
--- 4297,4303 ----
extern tree condition_conversion PARAMS ((tree));
extern tree target_type PARAMS ((tree));
extern tree require_complete_type PARAMS ((tree));
+ extern tree can_complete_type PARAMS ((tree));
extern tree complete_type PARAMS ((tree));
extern tree complete_type_or_else PARAMS ((tree, tree));
extern int type_unknown_p PARAMS ((tree));
diff -cprN gcc-31-save/gcc/cp/pt.c gcc-31-new/gcc/cp/pt.c
*** gcc-31-save/gcc/cp/pt.c Thu Jun 20 22:13:50 2002
--- gcc-31-new/gcc/cp/pt.c Sat Jun 29 20:55:53 2002
*************** instantiate_class_template (type)
*** 5203,5209 ****
if (DECL_INITIALIZED_IN_CLASS_P (r))
check_static_variable_definition (r, TREE_TYPE (r));
}
!
/* R will have a TREE_CHAIN if and only if it has already been
processed by finish_member_declaration. This can happen
if, for example, it is a TYPE_DECL for a class-scoped
--- 5203,5222 ----
if (DECL_INITIALIZED_IN_CLASS_P (r))
check_static_variable_definition (r, TREE_TYPE (r));
}
! else if (TREE_CODE (r) == FIELD_DECL)
! {
! /* Determine whether R has a valid type and can be
! completed later. If R is invalid, then it is replaced
! by error_mark_node so that it will not be added to
! TYPE_FIELDS. */
! tree rtype = TREE_TYPE (r);
! if (can_complete_type (rtype) == error_mark_node)
! {
! incomplete_type_error (r, rtype);
! r = error_mark_node;
! }
! }
!
/* R will have a TREE_CHAIN if and only if it has already been
processed by finish_member_declaration. This can happen
if, for example, it is a TYPE_DECL for a class-scoped
*************** instantiate_class_template (type)
*** 5226,5231 ****
--- 5239,5250 ----
finish_member_declaration (r);
}
+ /* Now that TYPE_FIELDS and TYPE_METHODS are set up. We can
+ instantiate templates used by this class. */
+ for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL)
+ complete_type (TREE_TYPE (t));
+
/* Construct the DECL_FRIENDLIST for the new class type. */
typedecl = TYPE_MAIN_DECL (type);
for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern));
*************** instantiate_class_template (type)
*** 5284,5296 ****
--processing_template_decl;
}
- for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- {
- TREE_TYPE (t) = complete_type (TREE_TYPE (t));
- require_complete_type (t);
- }
-
/* Set the file and line number information to whatever is given for
the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point
--- 5303,5308 ----
diff -cprN gcc-31-save/gcc/cp/typeck.c gcc-31-new/gcc/cp/typeck.c
*** gcc-31-save/gcc/cp/typeck.c Fri Jun 21 19:22:57 2002
--- gcc-31-new/gcc/cp/typeck.c Sat Jun 29 19:33:19 2002
*************** require_complete_type (value)
*** 124,129 ****
--- 124,148 ----
return error_mark_node;
}
+ /* Returns error_mark_node if TYPE cannot be completed later.
+ Otherwise returns TYPE. */
+
+ tree
+ can_complete_type (type)
+ tree type;
+ {
+ if (type == NULL_TREE)
+ return error_mark_node;
+ else if (type == error_mark_node || COMPLETE_TYPE_P (type))
+ return type;
+ else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+ return can_complete_type (TREE_TYPE (type));
+ else if (CLASS_TYPE_P (type) && TYPE_BEING_DEFINED (TYPE_MAIN_VARIANT (type)))
+ return error_mark_node;
+ else
+ return type;
+ }
+
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
a template instantiation, do the instantiation. Returns TYPE,
whether or not it could be completed, unless something goes
diff -cprN gcc-31-save/gcc/cp/typeck2.c gcc-31-new/gcc/cp/typeck2.c
*** gcc-31-save/gcc/cp/typeck2.c Sun May 19 17:07:30 2002
--- gcc-31-new/gcc/cp/typeck2.c Fri Jun 28 21:35:09 2002
*************** incomplete_type_error (value, type)
*** 196,202 ****
return;
if (value != 0 && (TREE_CODE (value) == VAR_DECL
! || TREE_CODE (value) == PARM_DECL))
{
cp_error_at ("`%D' has incomplete type", value);
decl = 1;
--- 196,203 ----
return;
if (value != 0 && (TREE_CODE (value) == VAR_DECL
! || TREE_CODE (value) == PARM_DECL
! || TREE_CODE (value) == FIELD_DECL))
{
cp_error_at ("`%D' has incomplete type", value);
decl = 1;
*************** retry:
*** 211,217 ****
case ENUMERAL_TYPE:
if (!decl)
error ("invalid use of undefined type `%#T'", type);
! cp_error_at ("forward declaration of `%#T'", type);
break;
case VOID_TYPE:
--- 212,221 ----
case ENUMERAL_TYPE:
if (!decl)
error ("invalid use of undefined type `%#T'", type);
! if (!TYPE_TEMPLATE_INFO (type))
! cp_error_at ("forward declaration of `%#T'", type);
! else
! cp_error_at ("declaration of `%#T'", type);
break;
case VOID_TYPE:
diff -cprN gcc-31-save/gcc/testsuite/g++.dg/template/instantiate1.C gcc-31-new/gcc/testsuite/g++.dg/template/instantiate1.C
*** gcc-31-save/gcc/testsuite/g++.dg/template/instantiate1.C Thu Jan 1 07:00:00 1970
--- gcc-31-new/gcc/testsuite/g++.dg/template/instantiate1.C Sat Jun 29 19:21:15 2002
***************
*** 0 ****
--- 1,21 ----
+ // { dg-do compile }
+ // Origin:
+
+ // PR c++/6716
+ // ICE in complex class structure when components are incomplete
+
+ template <class T> struct X {
+ T t; // { dg-error "incomplete" }
+ };
+
+ template <class T> struct Y { // { dg-error "instantiated" }
+ X<T> x;
+ };
+
+ template <class T> struct Z { // { dg-error "instantiated|declaration" }
+ Y<Z<T> > y;
+ };
+
+ struct ZZ : Z<int>
+ { // { dg-error "instantiated" }
+ };
More information about the Gcc-patches
mailing list