]> gcc.gnu.org Git - gcc.git/commitdiff
Core issue 287, PR c++/7639
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Wed, 30 Oct 2002 15:54:10 +0000 (15:54 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Wed, 30 Oct 2002 15:54:10 +0000 (15:54 +0000)
Core issue 287, PR c++/7639
* cp-tree.h (lang_type_class): Add decl_list field.
(CLASSTYPE_DECL_LIST): New macro.
(maybe_add_class_template_decl_list): Add declaration.
* class.c (duplicate_tag_error): Initialize CLASSTYPE_DECL_LIST.
(unreverse_member_declarations): Reverse CLASSTYPE_DECL_LIST.
(maybe_add_class_template_decl_list): New function.
(add_implicitly_declared_members): Use it.
* decl.c (maybe_process_template_type_declaration): Likewise.
(pushtag): Likewise.
* friend.c (add_friend): Likewise.
(make_friend_class): Likewise.
* semantics.c (finish_member_declaration): Likewise.
(begin_class_definition): Initialize CLASSTYPE_DECL_LIST.
* pt.c (instantiate_class_template): Use CLASSTYPE_DECL_LIST
to process members and friends in the order of declaration.

Core issue 287, PR c++/7639
* g++.dg/template/instantiate1.C: Adjust error location.
* g++.dg/template/instantiate3.C: New test.
* g++.old-deja/g++.pt/crash10.C: Adjust error location.
* g++.old-deja/g++.pt/derived3.C: Adjust error location.
* g++.old-deja/g++.pt/spec28.C: Reorder declaration.

From-SVN: r58654

13 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/friend.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/instantiate1.C
gcc/testsuite/g++.dg/template/instantiate3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/crash10.C
gcc/testsuite/g++.old-deja/g++.pt/derived3.C
gcc/testsuite/g++.old-deja/g++.pt/spec28.C

index dba4a0d0237b4cabbd45a8e9269cf03c816551ba..1dc2487d52618ed34e12264b19b4e9f7307cb71e 100644 (file)
@@ -1,3 +1,22 @@
+2002-10-30  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       Core issue 287, PR c++/7639
+       * cp-tree.h (lang_type_class): Add decl_list field.
+       (CLASSTYPE_DECL_LIST): New macro.
+       (maybe_add_class_template_decl_list): Add declaration.
+       * class.c (duplicate_tag_error): Initialize CLASSTYPE_DECL_LIST.
+       (unreverse_member_declarations): Reverse CLASSTYPE_DECL_LIST.
+       (maybe_add_class_template_decl_list): New function.
+       (add_implicitly_declared_members): Use it.
+       * decl.c (maybe_process_template_type_declaration): Likewise.
+       (pushtag): Likewise.
+       * friend.c (add_friend): Likewise.
+       (make_friend_class): Likewise.
+       * semantics.c (finish_member_declaration): Likewise.
+       (begin_class_definition): Initialize CLASSTYPE_DECL_LIST.
+       * pt.c (instantiate_class_template): Use CLASSTYPE_DECL_LIST
+       to process members and friends in the order of declaration.
+
 2002-10-29  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/8287
index 82631615a6f23a0605a8d98aaa6a9c25ddf31d7b..d189686fdcf4877b344de60f9a54fc75a805884c 100644 (file)
@@ -2093,6 +2093,7 @@ duplicate_tag_error (t)
       TYPE_REDEFINED (t) = 1;
       CLASSTYPE_TEMPLATE_INFO (t) = template_info;
       CLASSTYPE_USE_TEMPLATE (t) = use_template;
+      CLASSTYPE_DECL_LIST (t) = NULL_TREE;
     }
   TYPE_SIZE (t) = NULL_TREE;
   TYPE_MODE (t) = VOIDmode;
@@ -2744,6 +2745,29 @@ finish_struct_anon (t)
     }
 }
 
+/* Add T to CLASSTYPE_DECL_LIST of current_class_type which
+   will be used later during class template instantiation.
+   When FRIEND_P is zero, T can be a static member data (VAR_DECL),
+   a non-static member data (FIELD_DECL), a member function
+   (FUNCTION_DECL), a nested type (RECORD_TYPE, ENUM_TYPE), 
+   a typedef (TYPE_DECL) or a member class template (TEMPLATE_DECL)
+   When FRIEND_P is nonzero, T is either a friend class
+   (RECORD_TYPE, TEMPLATE_DECL) or a friend function
+   (FUNCTION_DECL, TEMPLATE_DECL).  */
+
+void
+maybe_add_class_template_decl_list (type, t, friend_p)
+     tree type;
+     tree t;
+     int friend_p;
+{
+  /* Save some memory by not creating TREE_LIST if TYPE is not template.  */
+  if (CLASSTYPE_TEMPLATE_INFO (type))
+    CLASSTYPE_DECL_LIST (type)
+      = tree_cons (friend_p ? NULL_TREE : type,
+                  t, CLASSTYPE_DECL_LIST (type));
+}
+
 /* Create default constructors, assignment operators, and so forth for
    the type indicated by T, if they are needed.
    CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
@@ -2824,7 +2848,10 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
   /* Now, hook all of the new functions on to TYPE_METHODS,
      and add them to the CLASSTYPE_METHOD_VEC.  */
   for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
-    add_method (t, *f, /*error_p=*/0);
+    {
+      add_method (t, *f, /*error_p=*/0);
+      maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
+    }
   *f = TYPE_METHODS (t);
   TYPE_METHODS (t) = implicit_fns;
 
@@ -5305,10 +5332,11 @@ unreverse_member_declarations (t)
   tree prev;
   tree x;
 
-  /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in
-     reverse order.  Put them in declaration order now.  */
+  /* The following lists are all in reverse order.  Put them in
+     declaration order now.  */
   TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
   CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t));
+  CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
 
   /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
      reverse order, so we can't just use nreverse.  */
index e1544fd6428c959175b0db2ab0791931cbf2936f..d9bde845c5523ab512071836db7131c12b673a39 100644 (file)
@@ -1159,6 +1159,7 @@ struct lang_type_class GTY(())
   tree friend_classes;
   tree rtti;
   tree methods;
+  tree decl_list;
   tree template_info;
   tree befriending_classes;
 };
@@ -1295,6 +1296,12 @@ struct lang_type GTY(())
    functions are sorted, once the class is complete.  */
 #define CLASSTYPE_METHOD_VEC(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->methods)
 
+/* For class templates, this is a TREE_LIST of all member data,
+   functions, types, and friends in the order of declaration.
+   The TREE_PURPOSE of each TREE_LIST is NULL_TREE for a friend,
+   and the RECORD_TYPE for the class template otherwise.  */
+#define CLASSTYPE_DECL_LIST(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->decl_list)
+
 /* The slot in the CLASSTYPE_METHOD_VEC where constructors go.  */
 #define CLASSTYPE_CONSTRUCTOR_SLOT 0
 
@@ -3572,6 +3579,7 @@ extern void cxx_print_error_function      PARAMS ((struct diagnostic_context *,
 extern void build_self_reference               PARAMS ((void));
 extern int same_signature_p                    PARAMS ((tree, tree));
 extern void warn_hidden                                PARAMS ((tree));
+extern void maybe_add_class_template_decl_list PARAMS ((tree, tree, int));
 extern tree get_enclosing_class                        PARAMS ((tree));
 int is_base_of_enclosing_class                 PARAMS ((tree, tree));
 extern void unreverse_member_declarations       PARAMS ((tree));
index f42c8d3fdabc89545e34a8201b3bc94689adcefd..4fcb36369ddb80204f266955b3c5d658d8af3bad 100644 (file)
@@ -2617,7 +2617,11 @@ maybe_process_template_type_declaration (type, globalize, b)
              b->level_chain->tags =
                tree_cons (name, type, b->level_chain->tags);
              if (!COMPLETE_TYPE_P (current_class_type))
-               CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+               {
+                 maybe_add_class_template_decl_list (current_class_type,
+                                                     type, /*friend_p=*/0);
+                 CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+               }
            }
        }
     }
@@ -2781,7 +2785,11 @@ pushtag (name, type, globalize)
       if (b->parm_flag == 2)
        {
          if (!COMPLETE_TYPE_P (current_class_type))
-           CLASSTYPE_TAGS (current_class_type) = b->tags;
+           {
+             maybe_add_class_template_decl_list (current_class_type,
+                                                 type, /*friend_p=*/0);
+             CLASSTYPE_TAGS (current_class_type) = b->tags;
+           }
        }
     }
 
index b71baa572827de8452fcae98e14075be7b99efbd..7b718ace0dfa26399ec672a1047e17722321291e 100644 (file)
@@ -159,6 +159,9 @@ add_friend (type, decl)
                  return;
                }
            }
+
+         maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
+
          TREE_VALUE (list) = tree_cons (error_mark_node, decl,
                                         TREE_VALUE (list));
          return;
@@ -166,6 +169,8 @@ add_friend (type, decl)
       list = TREE_CHAIN (list);
     }
 
+  maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
+
   DECL_FRIENDLIST (typedecl)
     = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
                 DECL_FRIENDLIST (typedecl));
@@ -267,6 +272,8 @@ make_friend_class (type, friend_type)
                TREE_VALUE (classes), type);
   else
     {
+      maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
+
       CLASSTYPE_FRIEND_CLASSES (type)
        = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
       if (is_template_friend)
index 183a360724f6c70e5a7002b986dd122592ade325..09e225add65d6504be23c8ad6ef54ff15d3d5452 100644 (file)
@@ -4975,7 +4975,7 @@ tree
 instantiate_class_template (type)
      tree type;
 {
-  tree template, args, pattern, t;
+  tree template, args, pattern, t, member;
   tree typedecl;
 
   if (type == error_mark_node)
@@ -5070,6 +5070,7 @@ instantiate_class_template (type)
       TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
       TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
       TYPE_METHODS (type) = TYPE_METHODS (pattern);
+      CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
       CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
       CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
       
@@ -5223,175 +5224,174 @@ instantiate_class_template (type)
      class.  */
   pushclass (type, 1);
 
-  for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
+  /* Now members are processed in the order of declaration.  */
+  for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
     {
-      tree tag = TREE_VALUE (t);
-      tree name = TYPE_IDENTIFIER (tag);
-      tree newtag;
+      tree t = TREE_VALUE (member);
 
-      newtag = tsubst (tag, args, tf_error, NULL_TREE);
-      my_friendly_assert (newtag != error_mark_node, 20010206);
-      if (TREE_CODE (newtag) != ENUMERAL_TYPE)
+      if (TREE_PURPOSE (member))
        {
-         if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
-           /* Unfortunately, lookup_template_class sets
-              CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
-              instantiation (i.e., for the type of a member template
-              class nested within a template class.)  This behavior is
-              required for maybe_process_partial_specialization to work
-              correctly, but is not accurate in this case; the TAG is not
-              an instantiation of anything.  (The corresponding
-              TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
-           CLASSTYPE_USE_TEMPLATE (newtag) = 0;
-
-         /* Now, we call pushtag to put this NEWTAG into the scope of
-            TYPE.  We first set up the IDENTIFIER_TYPE_VALUE to avoid
-            pushtag calling push_template_decl.  We don't have to do
-            this for enums because it will already have been done in
-            tsubst_enum.  */
-         if (name)
-           SET_IDENTIFIER_TYPE_VALUE (name, newtag);
-         pushtag (name, newtag, /*globalize=*/0);
-       }
-    }
+         if (TYPE_P (t))
+           {
+             /* Build new CLASSTYPE_TAGS.  */
 
-  /* Don't replace enum constants here.  */
-  for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
-    if (TREE_CODE (t) != CONST_DECL)
-      {
-       tree r;
+             tree tag = t;
+             tree name = TYPE_IDENTIFIER (tag);
+             tree newtag;
 
-       /* The the file and line for this declaration, to assist in
-          error message reporting.  Since we called push_tinst_level
-          above, we don't need to restore these.  */
-       lineno = DECL_SOURCE_LINE (t);
-       input_filename = DECL_SOURCE_FILE (t);
+             newtag = tsubst (tag, args, tf_error, NULL_TREE);
+             my_friendly_assert (newtag != error_mark_node, 20010206);
+             if (TREE_CODE (newtag) != ENUMERAL_TYPE)
+               {
+                 if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
+                   /* Unfortunately, lookup_template_class sets
+                      CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
+                      instantiation (i.e., for the type of a member template
+                      class nested within a template class.)  This behavior is
+                      required for maybe_process_partial_specialization to work
+                      correctly, but is not accurate in this case; the TAG is not
+                      an instantiation of anything.  (The corresponding
+                      TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
+                   CLASSTYPE_USE_TEMPLATE (newtag) = 0;
+
+                 /* Now, we call pushtag to put this NEWTAG into the scope of
+                    TYPE.  We first set up the IDENTIFIER_TYPE_VALUE to avoid
+                    pushtag calling push_template_decl.  We don't have to do
+                    this for enums because it will already have been done in
+                    tsubst_enum.  */
+                 if (name)
+                   SET_IDENTIFIER_TYPE_VALUE (name, newtag);
+                 pushtag (name, newtag, /*globalize=*/0);
+               }
+           }
+         else if (TREE_CODE (t) == FUNCTION_DECL 
+                  || DECL_FUNCTION_TEMPLATE_P (t))
+           {
+             /* Build new TYPE_METHODS.  */
 
-       r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
-       if (TREE_CODE (r) == VAR_DECL)
-         {
-           tree init;
+             tree r = tsubst (t, args, tf_error, NULL_TREE);
+             set_current_access_from_decl (r);
+             grok_special_member_properties (r);
+             finish_member_declaration (r);
+           }
+         else
+           {
+             /* Build new TYPE_FIELDS.  */
 
-           if (DECL_INITIALIZED_IN_CLASS_P (r))
-             init = tsubst_expr (DECL_INITIAL (t), args,
-                                 tf_error | tf_warning, NULL_TREE);
-           else
-             init = NULL_TREE;
+             if (TREE_CODE (t) != CONST_DECL)
+               {
+                 tree r;
 
-           finish_static_data_member_decl (r, init,
-                                           /*asmspec_tree=*/NULL_TREE, 
-                                           /*flags=*/0);
+                 /* The the file and line for this declaration, to assist
+                    in error message reporting.  Since we called 
+                    push_tinst_level above, we don't need to restore these.  */
+                 lineno = DECL_SOURCE_LINE (t);
+                 input_filename = DECL_SOURCE_FILE (t);
 
-           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_without_circularity (rtype))
-             {
-               cxx_incomplete_type_error (r, rtype);
-               r = error_mark_node;
-             }
-         }
+                 r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+                 if (TREE_CODE (r) == VAR_DECL)
+                   {
+                     tree init;
 
-       /* 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
-          ENUMERAL_TYPE; such a thing will already have been added to
-          the field list by tsubst_enum above.  */
-       if (!TREE_CHAIN (r))
-         {
-           set_current_access_from_decl (r);
-           finish_member_declaration (r);
-         }
-      }
+                     if (DECL_INITIALIZED_IN_CLASS_P (r))
+                       init = tsubst_expr (DECL_INITIAL (t), args,
+                                           tf_error | tf_warning, NULL_TREE);
+                     else
+                       init = NULL_TREE;
 
-  /* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
-     for this instantiation.  */
-  for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
-    {
-      tree r = tsubst (t, args, tf_error, NULL_TREE);
-      set_current_access_from_decl (r);
-      grok_special_member_properties (r);
-      finish_member_declaration (r);
-    }
+                     finish_static_data_member_decl (r, init,
+                                                     /*asmspec_tree=*/NULL_TREE, 
+                                                     /*flags=*/0);
 
-  /* Construct the DECL_FRIENDLIST for the new class type.  */
-  typedecl = TYPE_MAIN_DECL (type);
-  for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern));
-       t != NULL_TREE;
-       t = TREE_CHAIN (t))
-    {
-      tree friends;
-
-      for (friends = TREE_VALUE (t);
-          friends != NULL_TREE;
-          friends = TREE_CHAIN (friends))
-       if (TREE_PURPOSE (friends) == error_mark_node)
-         add_friend (type, 
-                     tsubst_friend_function (TREE_VALUE (friends),
-                                             args));
-       else
-         abort ();
-    }
-
-  for (t = CLASSTYPE_FRIEND_CLASSES (pattern);
-       t != NULL_TREE;
-       t = TREE_CHAIN (t))
-    {
-      tree friend_type = TREE_VALUE (t);
-      tree new_friend_type;
+                     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_without_circularity (rtype))
+                       complete_type (rtype);
+
+                     if (!COMPLETE_TYPE_P (rtype))
+                       {
+                         cxx_incomplete_type_error (r, rtype);
+                         r = error_mark_node;
+                       }
+                   }
 
-      if (TREE_CODE (friend_type) == TEMPLATE_DECL)
-       new_friend_type = tsubst_friend_class (friend_type, args);
-      else if (uses_template_parms (friend_type))
-       new_friend_type = tsubst (friend_type, args,
-                                 tf_error | tf_warning, NULL_TREE);
-      else 
-       {
-         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 it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
+                    such a thing will already have been added to the field
+                    list by tsubst_enum in finish_member_declaration in the
+                    CLASSTYPE_TAGS case above.  */
+                 if (!(TREE_CODE (r) == TYPE_DECL
+                       && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
+                       && TYPE_CONTEXT (TREE_TYPE (r)) == type))
+                   {
+                     set_current_access_from_decl (r);
+                     finish_member_declaration (r);
+                   }
+               }
+           }
        }
+      else
+       {
+         if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t))
+           {
+             /* Build new CLASSTYPE_FRIEND_CLASSES.  */
 
-      if (TREE_CODE (friend_type) == TEMPLATE_DECL)
-       /* Trick make_friend_class into realizing that the friend
-          we're adding is a template, not an ordinary class.  It's
-          important that we use make_friend_class since it will
-          perform some error-checking and output cross-reference
-          information.  */
-       ++processing_template_decl;
+             tree friend_type = t;
+             tree new_friend_type;
 
-      if (new_friend_type != error_mark_node)
-        make_friend_class (type, new_friend_type);
+             if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+               new_friend_type = tsubst_friend_class (friend_type, args);
+             else if (uses_template_parms (friend_type))
+               new_friend_type = tsubst (friend_type, args,
+                                         tf_error | tf_warning, NULL_TREE);
+             else 
+               {
+                 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)
-       --processing_template_decl;
-    }
+             if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+               /* Trick make_friend_class into realizing that the friend
+                  we're adding is a template, not an ordinary class.  It's
+                  important that we use make_friend_class since it will
+                  perform some error-checking and output cross-reference
+                  information.  */
+               ++processing_template_decl;
 
-  /* 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)
-      {
-       TREE_TYPE (t) = complete_type (TREE_TYPE (t));
-       require_complete_type (t);
-      }
+             if (new_friend_type != error_mark_node)
+               make_friend_class (type, new_friend_type);
+
+             if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+               --processing_template_decl;
+           }
+         else
+           {
+             /* Build new DECL_FRIENDLIST.  */
+
+             add_friend (type, 
+                         tsubst_friend_function (t, args));
+           }
+       }
+    }
 
   /* 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
      that would be used for non-template classes.  */
+  typedecl = TYPE_MAIN_DECL (type);
   lineno = DECL_SOURCE_LINE (typedecl);
   input_filename = DECL_SOURCE_FILE (typedecl);
 
index e2428a916e1e4ec2acd56522e23f20d3b5a514e9..81b4ccfdafc4e8faddc45bda99b794bf335f72e8 100644 (file)
@@ -1754,6 +1754,7 @@ begin_class_definition (t)
          TYPE_BINFO_BASETYPES (t) = NULL_TREE;
          TYPE_FIELDS (t) = NULL_TREE;
          TYPE_METHODS (t) = NULL_TREE;
+         CLASSTYPE_DECL_LIST (t) = NULL_TREE;
          CLASSTYPE_TAGS (t) = NULL_TREE;
          CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
          TYPE_SIZE (t) = NULL_TREE;
@@ -1835,6 +1836,8 @@ finish_member_declaration (decl)
   if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
     SET_DECL_LANGUAGE (decl, lang_cplusplus);
 
+  maybe_add_class_template_decl_list (current_class_type, decl, /*friend_p=*/0);
+
   /* Put functions on the TYPE_METHODS list and everything else on the
      TYPE_FIELDS list.  Note that these are built up in reverse order.
      We reverse them (to obtain declaration order) in finish_struct.  */
index ed1f82e4cf493e8760b6447e378b28bbc9b49b7b..2c0826d0b30d3d9cdd867539e26a31ad2b5cda08 100644 (file)
@@ -1,3 +1,12 @@
+2002-10-30  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       Core issue 287, PR c++/7639
+       * g++.dg/template/instantiate1.C: Adjust error location.
+       * g++.dg/template/instantiate3.C: New test.
+       * g++.old-deja/g++.pt/crash10.C: Adjust error location.
+       * g++.old-deja/g++.pt/derived3.C: Adjust error location.
+       * g++.old-deja/g++.pt/spec28.C: Reorder declaration.
+
 2002-10-29  Hans-Peter Nilsson  <hp@bitrange.com>
 
        * lib/compat.exp (compat-execute): Don't clean out a gluefile.
index e96bcd283fd28837d55f2d00f4f89f5a37e8370f..e4e7bc981785abc40d356a997de210f8b62de1bf 100644 (file)
@@ -8,12 +8,12 @@ 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 Y {
+  X<T> x;                      // { dg-error "instantiated" }
 };
 
-template <class T> struct Z {  // { dg-error "instantiated|declaration" }
-  Y<Z<T> > y;
+template <class T> struct Z {  // { dg-error "declaration" }
+  Y<Z<T> > y;                  // { dg-error "instantiated" }
 };
 
 struct ZZ : Z<int>
diff --git a/gcc/testsuite/g++.dg/template/instantiate3.C b/gcc/testsuite/g++.dg/template/instantiate3.C
new file mode 100644 (file)
index 0000000..e75b570
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// Origin: Scott Snyder <snyder@fnal.gov>
+
+// PR c++/7639
+// ICE when accessing member with incomplete type.
+
+class ACE_Null_Mutex;  // { dg-error "forward declaration" }
+
+template <class TYPE>
+struct ACE_Cleanup_Adapter
+{
+  TYPE &object ()
+  { return object_; }  // { dg-error "no member" }
+  TYPE object_;                // { dg-error "incomplete type" }
+};
+
+template class ACE_Cleanup_Adapter<ACE_Null_Mutex>; // { dg-error "instantiated from here" }
index 033e2341c24190e3de792185f86b387e3548e875..a7633a0d58ead97aecb9f86c5746c832b4732b09 100644 (file)
@@ -3,9 +3,9 @@
 template<int M, int N>
 class GCD {
 public:
-  enum { val = (N == 0) ? M : GCD<N, M % N>::val }; 
+  enum { val = (N == 0) ? M : GCD<N, M % N>::val }; // ERROR - division
 };
 
 int main() {
-  GCD< 1, 0 >::val; // ERROR - division
+  GCD< 1, 0 >::val; // ERROR - instantiated
 }
index fa807da60fa568b3993ac338a66e7a627899a877..262c1c7df7901c314c811af4f4fc713a4a3e242f 100644 (file)
@@ -6,10 +6,10 @@
 
 template<class T>
 class X {
-       class Y : public T {}; // ERROR - invalid base type
-       Y y;
+       class Y : public T {};
+       Y y;                    // ERROR - invalid base type
 };
 int main() {
-       X<int> x;
+       X<int> x;               // ERROR - instantiated
 }
 
index d63e7967672edfeaf0bb7ebe476fc56013002a8c..cb073802a925b3127795707f6edae557c638e5a0 100644 (file)
@@ -2,8 +2,8 @@
 
 template <class T> 
 struct S1 {
-  friend bool f<>(const S1&);
   typedef T X;
+  friend bool f<>(const S1&);
 };
 
 template <class T>
This page took 0.121887 seconds and 5 git commands to generate.