[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