OSDN Git Service

* typeck.c (require_complete_type): Use complete_type_or_else.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Aug 1998 16:33:34 +0000 (16:33 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Aug 1998 16:33:34 +0000 (16:33 +0000)
(complete_type_or_else): Always return NULL_TREE on failure, as
documented.
* pt.c (tsubst_aggr_type): Prototype.
(tsubst_decl): New function, split out from tsubst.  Set
input_filename and lineno as appropriate.
(pop_tinst_level): Restore the file and line number saved in
push_tinst_level.
(instantiate_class_template): Set input_filename and lineno as
appropriate.
(tsubst): Move _DECL processing to tsubst_decl.  Make sure the
context for a TYPENAME_TYPE is complete.
* decl2.c (grokbitfield): Issue errors on bitfields declared with
function type.
(do_dtors): As in do_ctors, pretend to be a member of the same
class as a static data member while generating a call to its
destructor.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@21627 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C
gcc/testsuite/g++.old-deja/g++.law/visibility13.C
gcc/testsuite/g++.old-deja/g++.other/dtor2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/friend23.C
gcc/testsuite/g++.old-deja/g++.pt/t05.C
gcc/testsuite/g++.old-deja/g++.pt/typename8.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
gcc/testsuite/g++.old-deja/g++.robertl/eb128.C

index f1957d8..4a1c42a 100644 (file)
@@ -1,6 +1,26 @@
 1998-08-07  Mark Mitchell  <mark@markmitchell.com>
 
-       * cvt.c (cp_convert_to_pointer): Handle a NULL pointer
+       * typeck.c (require_complete_type): Use complete_type_or_else.
+       (complete_type_or_else): Always return NULL_TREE on failure, as
+       documented.
+
+       * pt.c (tsubst_aggr_type): Prototype.
+       (tsubst_decl): New function, split out from tsubst.  Set
+       input_filename and lineno as appropriate.
+       (pop_tinst_level): Restore the file and line number saved in
+       push_tinst_level.
+       (instantiate_class_template): Set input_filename and lineno as
+       appropriate.
+       (tsubst): Move _DECL processing to tsubst_decl.  Make sure the
+       context for a TYPENAME_TYPE is complete.
+
+       * decl2.c (grokbitfield): Issue errors on bitfields declared with
+       function type.
+       (do_dtors): As in do_ctors, pretend to be a member of the same
+       class as a static data member while generating a call to its
+       destructor.
+
+       * cvt.c (cp_convert_to_pointer): Handle NULL pointer
        conversions, even in complex virtual base class hierarchies.
 
 1998-08-06  Mark Mitchell  <mark@markmitchell.com>
index 998b346..d8bc74f 100644 (file)
@@ -1845,6 +1845,17 @@ grokbitfield (declarator, declspecs, width)
       return NULL_TREE;
     }
 
+  /* Usually, finish_struct_1 catches bitifields with invalid types.
+     But, in the case of bitfields with function type, we confuse
+     ourselves into thinking they are member functions, so we must
+     check here.  */
+  if (TREE_CODE (value) == FUNCTION_DECL)
+    {
+      cp_error ("cannot declare bitfield `%D' with funcion type",
+               DECL_NAME (value));
+      return NULL_TREE;
+    }
+
   if (IS_SIGNATURE (current_class_type))
     {
       error ("field declaration not allowed in signature");
@@ -3001,6 +3012,25 @@ do_dtors ()
          if (! current_function_decl)
            start_objects ('D');
 
+         /* Because of:
+
+              [class.access.spec]
+
+              Access control for implicit calls to the constructors,
+              the conversion functions, or the destructor called to
+              create and destroy a static data member is per- formed as
+              if these calls appeared in the scope of the member's
+              class.  
+
+            we must convince enforce_access to let us access the
+            DECL.  */
+         if (member_p (decl))
+           {
+             DECL_CLASS_CONTEXT (current_function_decl)
+               = DECL_CONTEXT (decl);
+             DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
+           }
+
          temp = build_cleanup (decl);
 
          if (protect)
@@ -3015,6 +3045,11 @@ do_dtors ()
 
          if (protect)
            expand_end_cond ();
+         
+         /* Now that we're done with DECL we don't need to pretend to
+            be a member of its class any longer.  */
+         DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
+         DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
        }
     }
 
index 3071f1e..f664caa 100644 (file)
@@ -122,6 +122,8 @@ static tree most_specialized_class PROTO((tree, tree));
 static tree most_general_template PROTO((tree));
 static void set_mangled_name_for_template_decl PROTO((tree));
 static int template_class_depth_real PROTO((tree, int));
+static tree tsubst_aggr_type PROTO((tree, tree, tree, int));
+static tree tsubst_decl PROTO((tree, tree, tree, tree));
 
 /* We use TREE_VECs to hold template arguments.  If there is only one
    level of template arguments, then the TREE_VEC contains the
@@ -3779,6 +3781,11 @@ pop_tinst_level ()
 {
   struct tinst_level *old = current_tinst_level;
 
+  /* Restore the filename and line number stashed away when we started
+     this instantiation.  */
+  lineno = old->line;
+  input_filename = old->file;
+  
   current_tinst_level = old->next;
   old->next = free_tinst_level;
   free_tinst_level = old;
@@ -4291,7 +4298,15 @@ instantiate_class_template (type)
   for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
     if (TREE_CODE (t) != CONST_DECL)
       {
-       tree r = tsubst (t, args, NULL_TREE);
+       tree r;
+
+       /* 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);
+
+       r = tsubst (t, args, NULL_TREE);
        if (TREE_CODE (r) == VAR_DECL)
          {
            pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
@@ -4619,204 +4634,34 @@ tsubst_aggr_type (t, args, in_decl, entering_scope)
     }
 }
 
-/* Take the tree structure T and replace template parameters used therein
-   with the argument vector ARGS.  IN_DECL is an associated decl for
-   diagnostics.
-
-   tsubst is used for dealing with types, decls and the like; for
-   expressions, use tsubst_expr or tsubst_copy.  */
+/* Substitute the ARGS into the T, which is a _DECL.  TYPE is the
+   (already computed) substitution of ARGS into TREE_TYPE (T), if
+   appropriate.  Return the result of the substitution.  IN_DECL is as
+   for tsubst.  */
 
 tree
-tsubst (t, args, in_decl)
-     tree t, args;
+tsubst_decl (t, args, type, in_decl)
+     tree t;
+     tree args;
+     tree type;
      tree in_decl;
 {
-  tree type;
-
-  if (t == NULL_TREE || t == error_mark_node
-      || t == integer_type_node
-      || t == void_type_node
-      || t == char_type_node
-      || TREE_CODE (t) == NAMESPACE_DECL)
-    return t;
-
-  if (TREE_CODE (t) == IDENTIFIER_NODE)
-    type = IDENTIFIER_TYPE_VALUE (t);
-  else
-    type = TREE_TYPE (t);
-  if (type == unknown_type_node)
-    my_friendly_abort (42);
+  int saved_lineno;
+  char* saved_filename;
+  tree r;
 
-  if (type && TREE_CODE (t) != FUNCTION_DECL
-      && TREE_CODE (t) != TYPENAME_TYPE
-      && TREE_CODE (t) != TEMPLATE_DECL
-      && TREE_CODE (t) != IDENTIFIER_NODE)
-    type = tsubst (type, args, in_decl);
+  /* Set the filename and linenumber to improve error-reporting.  */
+  saved_lineno = lineno;
+  saved_filename = input_filename;
+  lineno = DECL_SOURCE_LINE (t);
+  input_filename = DECL_SOURCE_FILE (t);
 
   switch (TREE_CODE (t))
     {
-    case RECORD_TYPE:
-    case UNION_TYPE:
-    case ENUMERAL_TYPE:
-      return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
-
-    case ERROR_MARK:
-    case IDENTIFIER_NODE:
-    case OP_IDENTIFIER:
-    case VOID_TYPE:
-    case REAL_TYPE:
-    case COMPLEX_TYPE:
-    case BOOLEAN_TYPE:
-    case INTEGER_CST:
-    case REAL_CST:
-    case STRING_CST:
-    case NAMESPACE_DECL:
-      return t;
-
-    case INTEGER_TYPE:
-      if (t == integer_type_node)
-       return t;
-
-      if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
-         && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
-       return t;
-
-      {
-       tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
-       max = tsubst_expr (max, args, in_decl);
-       if (processing_template_decl)
-         {
-           tree itype = make_node (INTEGER_TYPE);
-           TYPE_MIN_VALUE (itype) = size_zero_node;
-           TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
-                                               integer_one_node);
-           return itype;
-         }
-
-       max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
-       return build_index_2_type (size_zero_node, max);
-      }
-
-    case TEMPLATE_TYPE_PARM:
-    case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_PARM_INDEX:
-      {
-       int idx;
-       int level;
-       int levels;
-       tree r = NULL_TREE;
-
-       if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-           || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
-         {
-           idx = TEMPLATE_TYPE_IDX (t);
-           level = TEMPLATE_TYPE_LEVEL (t);
-         }
-       else
-         {
-           idx = TEMPLATE_PARM_IDX (t);
-           level = TEMPLATE_PARM_LEVEL (t);
-         }
-
-       if (TREE_VEC_LENGTH (args) > 0)
-         {
-           tree arg = NULL_TREE;
-
-           levels = TMPL_ARGS_DEPTH (args);
-           if (level <= levels)
-             arg = TMPL_ARG (args, level, idx);
-
-           if (arg != NULL_TREE)
-             {
-               if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-                 {
-                   my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
-                                       == 't', 0);
-                   return cp_build_type_variant
-                     (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
-                      TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
-                 }
-               else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
-                 {
-                   if (CLASSTYPE_TEMPLATE_INFO (t))
-                     {
-                       /* We are processing a type constructed from
-                          a template template parameter */
-                       tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
-                                             args, in_decl);
-                       tree r;
-
-                       /* We can get a TEMPLATE_TEMPLATE_PARM here when 
-                          we are resolving nested-types in the signature of 
-                          a member function templates.
-                          Otherwise ARG is a TEMPLATE_DECL and is the real 
-                          template to be instantiated.  */
-                       if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
-                         arg = TYPE_NAME (arg);
-
-                       r = lookup_template_class (DECL_NAME (arg), 
-                                                  argvec, in_decl, 
-                                                  DECL_CONTEXT (arg),
-                                                  /*entering_scope=*/0);
-                       return cp_build_type_variant (r, TYPE_READONLY (t),
-                                                     TYPE_VOLATILE (t));
-                     }
-                   else
-                     /* We are processing a template argument list.  */ 
-                     return arg;
-                 }
-               else
-                 return arg;
-             }
-         }
-
-       if (level == 1)
-         /* This can happen during the attempted tsubst'ing in
-            unify.  This means that we don't yet have any information
-            about the template parameter in question.  */
-         return t;
-
-       /* If we get here, we must have been looking at a parm for a
-          more deeply nested template.  Make a new version of this
-          template parameter, but with a lower level.  */
-       switch (TREE_CODE (t))
-         {
-         case TEMPLATE_TYPE_PARM:
-         case TEMPLATE_TEMPLATE_PARM:
-           r = copy_node (t);
-           TEMPLATE_TYPE_PARM_INDEX (r)
-             = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
-                                           r, levels);
-           TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
-           TYPE_MAIN_VARIANT (r) = r;
-           TYPE_POINTER_TO (r) = NULL_TREE;
-           TYPE_REFERENCE_TO (r) = NULL_TREE;
-
-           if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
-               && CLASSTYPE_TEMPLATE_INFO (t))
-             {
-               tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
-               CLASSTYPE_TEMPLATE_INFO (r)
-                 = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
-             }
-           break;
-
-         case TEMPLATE_PARM_INDEX:
-           r = reduce_template_parm_level (t, type, levels);
-           break;
-          
-         default:
-           my_friendly_abort (0);
-         }
-
-       return r;
-      }
-
     case TEMPLATE_DECL:
       {
        /* We can get here when processing a member template function
           of a template class.  */
-       tree tmpl;
        tree decl = DECL_TEMPLATE_RESULT (t);
        tree parms;
        tree* new_parms;
@@ -4841,7 +4686,10 @@ tsubst (t, args, in_decl)
 
            spec = retrieve_specialization (t, full_args);
            if (spec != NULL_TREE)
-             return spec;
+             {
+               r = spec;
+               break;
+             }
          }
 
        /* Make a new template decl.  It will be similar to the
@@ -4849,60 +4697,60 @@ tsubst (t, args, in_decl)
           We also create a new function declaration, which is just
           like the old one, but points to this new template, rather
           than the old one.  */
-       tmpl = copy_node (t);
-       copy_lang_decl (tmpl);
-       my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
-       TREE_CHAIN (tmpl) = NULL_TREE;
+       r = copy_node (t);
+       copy_lang_decl (r);
+       my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
+       TREE_CHAIN (r) = NULL_TREE;
 
        if (is_template_template_parm)
          {
            tree new_decl = tsubst (decl, args, in_decl);
-           DECL_RESULT (tmpl) = new_decl;
-           TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
-           return tmpl;
+           DECL_RESULT (r) = new_decl;
+           TREE_TYPE (r) = TREE_TYPE (new_decl);
+           break;
          }
 
-       DECL_CONTEXT (tmpl
+       DECL_CONTEXT (r
          = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
                              /*entering_scope=*/1);
-       DECL_CLASS_CONTEXT (tmpl
+       DECL_CLASS_CONTEXT (r
          = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl,
                              /*entering_scope=*/1);
-       DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
+       DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
 
        if (TREE_CODE (decl) == TYPE_DECL)
          {
            tree new_type = tsubst (TREE_TYPE (t), args, in_decl);
-           TREE_TYPE (tmpl) = new_type;
-           CLASSTYPE_TI_TEMPLATE (new_type) = tmpl;
-           DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type);
-           DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type);
+           TREE_TYPE (r) = new_type;
+           CLASSTYPE_TI_TEMPLATE (new_type) = r;
+           DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
+           DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
          }
        else
          {
            tree new_decl = tsubst (decl, args, in_decl);
-           DECL_RESULT (tmpl) = new_decl;
-           DECL_TI_TEMPLATE (new_decl) = tmpl;
-           TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
-           DECL_TI_ARGS (tmpl) = DECL_TI_ARGS (new_decl);
+           DECL_RESULT (r) = new_decl;
+           DECL_TI_TEMPLATE (new_decl) = r;
+           TREE_TYPE (r) = TREE_TYPE (new_decl);
+           DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
          }
 
-       SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
-       DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
-       DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
+       SET_DECL_IMPLICIT_INSTANTIATION (r);
+       DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
+       DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
 
        /* The template parameters for this new template are all the
           template parameters for the old template, except the
           outermost level of parameters. */
-       DECL_TEMPLATE_PARMS (tmpl
+       DECL_TEMPLATE_PARMS (r
          = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
 
        if (PRIMARY_TEMPLATE_P (t))
-         DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+         DECL_PRIMARY_TEMPLATE (r) = r;
 
        /* We don't partially instantiate partial specializations.  */
        if (TREE_CODE (decl) == TYPE_DECL)
-         return tmpl;
+         break;
 
        for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
             spec != NULL_TREE;
@@ -4953,20 +4801,19 @@ tsubst (t, args, in_decl)
            new_fn = tsubst (DECL_RESULT (most_general_template (fn)), 
                             spec_args, in_decl); 
            DECL_TI_TEMPLATE (new_fn) = fn;
-           register_specialization (new_fn, tmpl
+           register_specialization (new_fn, r
                                     innermost_args (spec_args));
          }
 
        /* Record this partial instantiation.  */
-       register_specialization (tmpl, t, 
-                                DECL_TI_ARGS (DECL_RESULT (tmpl)));
+       register_specialization (r, t, 
+                                DECL_TI_ARGS (DECL_RESULT (r)));
 
-       return tmpl;
       }
+      break;
 
     case FUNCTION_DECL:
       {
-       tree r = NULL_TREE;
        tree ctx;
        tree argvec;
        tree gen_tmpl;
@@ -4988,7 +4835,10 @@ tsubst (t, args, in_decl)
            /* Check to see if we already have this specialization.  */
            spec = retrieve_specialization (gen_tmpl, argvec);
            if (spec)
-             return spec;
+             {
+               r = spec;
+               break;
+             }
          }
        else
          {
@@ -5113,13 +4963,12 @@ tsubst (t, args, in_decl)
                    == NULL_TREE))
              SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
          }
-
-       return r;
       }
+      break;
 
     case PARM_DECL:
       {
-       tree r = copy_node (t);
+       r = copy_node (t);
        TREE_TYPE (r) = type;
        if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
          DECL_INITIAL (r) = TREE_TYPE (r);
@@ -5135,12 +4984,12 @@ tsubst (t, args, in_decl)
 #endif
        if (TREE_CHAIN (t))
          TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
-       return r;
       }
+      break;
 
     case FIELD_DECL:
       {
-       tree r = copy_node (t);
+       r = copy_node (t);
        TREE_TYPE (r) = type;
        copy_lang_decl (r);
 #if 0
@@ -5150,21 +4999,20 @@ tsubst (t, args, in_decl)
        TREE_CHAIN (r) = NULL_TREE;
        if (TREE_CODE (type) == VOID_TYPE)
          cp_error_at ("instantiation of `%D' as type void", r);
-       return r;
       }
+      break;
 
     case USING_DECL:
       {
-       tree r = copy_node (t);
+       r = copy_node (t);
        DECL_INITIAL (r)
          = tsubst_copy (DECL_INITIAL (t), args, in_decl);
        TREE_CHAIN (r) = NULL_TREE;
-       return r;
       }
+      break;
 
     case VAR_DECL:
       {
-       tree r;
        tree argvec;
        tree gen_tmpl;
        tree spec;
@@ -5183,7 +5031,10 @@ tsubst (t, args, in_decl)
        spec = retrieve_specialization (gen_tmpl, argvec);
        
        if (spec)
-         return spec;
+         {
+           r = spec;
+           break;
+         }
 
        r = copy_node (t);
        TREE_TYPE (r) = type;
@@ -5207,20 +5058,227 @@ tsubst (t, args, in_decl)
        TREE_CHAIN (r) = NULL_TREE;
        if (TREE_CODE (type) == VOID_TYPE)
          cp_error_at ("instantiation of `%D' as type void", r);
-       return r;
       }
+      break;
 
     case TYPE_DECL:
       if (t == TYPE_NAME (TREE_TYPE (t)))
-       return TYPE_NAME (type);
+       r = TYPE_NAME (type);
+      else
+       {
+         r = copy_node (t);
+         TREE_TYPE (r) = type;
+         DECL_CONTEXT (r) = current_class_type;
+         TREE_CHAIN (r) = NULL_TREE;
+       }
+      break;
+
+    default:
+      my_friendly_abort (0);
+    } 
+
+  /* Restore the file and line information.  */
+  lineno = saved_lineno;
+  input_filename = saved_filename;
+
+  return r;
+}
+
+
+/* Take the tree structure T and replace template parameters used therein
+   with the argument vector ARGS.  IN_DECL is an associated decl for
+   diagnostics.
+
+   tsubst is used for dealing with types, decls and the like; for
+   expressions, use tsubst_expr or tsubst_copy.  */
+
+tree
+tsubst (t, args, in_decl)
+     tree t, args;
+     tree in_decl;
+{
+  tree type;
+
+  if (t == NULL_TREE || t == error_mark_node
+      || t == integer_type_node
+      || t == void_type_node
+      || t == char_type_node
+      || TREE_CODE (t) == NAMESPACE_DECL)
+    return t;
+
+  if (TREE_CODE (t) == IDENTIFIER_NODE)
+    type = IDENTIFIER_TYPE_VALUE (t);
+  else
+    type = TREE_TYPE (t);
+  if (type == unknown_type_node)
+    my_friendly_abort (42);
+
+  if (type && TREE_CODE (t) != FUNCTION_DECL
+      && TREE_CODE (t) != TYPENAME_TYPE
+      && TREE_CODE (t) != TEMPLATE_DECL
+      && TREE_CODE (t) != IDENTIFIER_NODE)
+    type = tsubst (type, args, in_decl);
+
+  if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+    return tsubst_decl (t, args, type, in_decl);
+
+  switch (TREE_CODE (t))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case ENUMERAL_TYPE:
+      return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
+
+    case ERROR_MARK:
+    case IDENTIFIER_NODE:
+    case OP_IDENTIFIER:
+    case VOID_TYPE:
+    case REAL_TYPE:
+    case COMPLEX_TYPE:
+    case BOOLEAN_TYPE:
+    case INTEGER_CST:
+    case REAL_CST:
+    case STRING_CST:
+      return t;
+
+    case INTEGER_TYPE:
+      if (t == integer_type_node)
+       return t;
+
+      if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
+         && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+       return t;
 
       {
-       tree r = copy_node (t);
-       TREE_TYPE (r) = type;
-       DECL_CONTEXT (r) = current_class_type;
-       TREE_CHAIN (r) = NULL_TREE;
+       tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
+       max = tsubst_expr (max, args, in_decl);
+       if (processing_template_decl)
+         {
+           tree itype = make_node (INTEGER_TYPE);
+           TYPE_MIN_VALUE (itype) = size_zero_node;
+           TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
+                                               integer_one_node);
+           return itype;
+         }
+
+       max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
+       return build_index_2_type (size_zero_node, max);
+      }
+
+    case TEMPLATE_TYPE_PARM:
+    case TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_PARM_INDEX:
+      {
+       int idx;
+       int level;
+       int levels;
+       tree r = NULL_TREE;
+
+       if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+           || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+         {
+           idx = TEMPLATE_TYPE_IDX (t);
+           level = TEMPLATE_TYPE_LEVEL (t);
+         }
+       else
+         {
+           idx = TEMPLATE_PARM_IDX (t);
+           level = TEMPLATE_PARM_LEVEL (t);
+         }
+
+       if (TREE_VEC_LENGTH (args) > 0)
+         {
+           tree arg = NULL_TREE;
+
+           levels = TMPL_ARGS_DEPTH (args);
+           if (level <= levels)
+             arg = TMPL_ARG (args, level, idx);
+
+           if (arg != NULL_TREE)
+             {
+               if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+                 {
+                   my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
+                                       == 't', 0);
+                   return cp_build_type_variant
+                     (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
+                      TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+                 }
+               else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+                 {
+                   if (CLASSTYPE_TEMPLATE_INFO (t))
+                     {
+                       /* We are processing a type constructed from
+                          a template template parameter */
+                       tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
+                                             args, in_decl);
+                       tree r;
+
+                       /* We can get a TEMPLATE_TEMPLATE_PARM here when 
+                          we are resolving nested-types in the signature of 
+                          a member function templates.
+                          Otherwise ARG is a TEMPLATE_DECL and is the real 
+                          template to be instantiated.  */
+                       if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+                         arg = TYPE_NAME (arg);
+
+                       r = lookup_template_class (DECL_NAME (arg), 
+                                                  argvec, in_decl, 
+                                                  DECL_CONTEXT (arg),
+                                                  /*entering_scope=*/0);
+                       return cp_build_type_variant (r, TYPE_READONLY (t),
+                                                     TYPE_VOLATILE (t));
+                     }
+                   else
+                     /* We are processing a template argument list.  */ 
+                     return arg;
+                 }
+               else
+                 return arg;
+             }
+         }
+
+       if (level == 1)
+         /* This can happen during the attempted tsubst'ing in
+            unify.  This means that we don't yet have any information
+            about the template parameter in question.  */
+         return t;
+
+       /* If we get here, we must have been looking at a parm for a
+          more deeply nested template.  Make a new version of this
+          template parameter, but with a lower level.  */
+       switch (TREE_CODE (t))
+         {
+         case TEMPLATE_TYPE_PARM:
+         case TEMPLATE_TEMPLATE_PARM:
+           r = copy_node (t);
+           TEMPLATE_TYPE_PARM_INDEX (r)
+             = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+                                           r, levels);
+           TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+           TYPE_MAIN_VARIANT (r) = r;
+           TYPE_POINTER_TO (r) = NULL_TREE;
+           TYPE_REFERENCE_TO (r) = NULL_TREE;
+
+           if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+               && CLASSTYPE_TEMPLATE_INFO (t))
+             {
+               tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+               CLASSTYPE_TEMPLATE_INFO (r)
+                 = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
+             }
+           break;
+
+         case TEMPLATE_PARM_INDEX:
+           r = reduce_template_parm_level (t, type, levels);
+           break;
+          
+         default:
+           my_friendly_abort (0);
+         }
+
        return r;
-      }          
+      }
 
     case TREE_LIST:
       {
@@ -5439,6 +5497,19 @@ tsubst (t, args, in_decl)
        tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl,
                                     /*entering_scope=*/1);
        tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
+
+       /* Normally, make_typename_type does not require that the CTX
+          have complete type in order to allow things like:
+            
+             template <class T> struct S { typename S<T>::X Y; };
+
+          But, such constructs have already been resolved by this
+          point, so here CTX really should have complete type, unless
+          it's a partial instantiation.  */
+       if (!uses_template_parms (ctx) 
+           && !complete_type_or_else (ctx))
+         return error_mark_node;
+
        f = make_typename_type (ctx, f);
        return cp_build_type_variant
          (f, TYPE_READONLY (f) || TYPE_READONLY (t),
index 3e4fd0a..008a315 100644 (file)
@@ -80,7 +80,9 @@ target_type (type)
 }
 
 /* Do `exp = require_complete_type (exp);' to make sure exp
-   does not have an incomplete type.  (That includes void types.)  */
+   does not have an incomplete type.  (That includes void types.)
+   Returns the error_mark_node if the VALUE does not have
+   complete type when this function returns.  */
 
 tree
 require_complete_type (value)
@@ -120,13 +122,10 @@ require_complete_type (value)
       return require_complete_type (value);
     }
 
-  if (TYPE_SIZE (complete_type (type)))
+  if (complete_type_or_else (type))
     return value;
   else
-    {
-      incomplete_type_error (value, type);
-      return error_mark_node;
-    }
+    return error_mark_node;
 }
 
 /* Try to complete TYPE, if it is incomplete.  For example, if TYPE is
@@ -170,7 +169,10 @@ complete_type_or_else (type)
      tree type;
 {
   type = complete_type (type);
-  if (type != error_mark_node && !TYPE_SIZE (type))
+  if (type == error_mark_node)
+    /* We already issued an error.  */
+    return NULL_TREE;
+  else if (!TYPE_SIZE (type))
     {
       incomplete_type_error (NULL_TREE, type);
       return NULL_TREE;
index 4e636b5..946e6d1 100644 (file)
@@ -9,7 +9,7 @@
 typedef void (func_type) ();
 
 struct s {
-  func_type f:32;      // ERROR - XFAIL *-*-*
+  func_type f:32;      // ERROR - bitified with function type
 };
 
 int main () { return 0; }
index 6e53fc7..8bd6a85 100644 (file)
@@ -14,7 +14,7 @@
 const int ArraySize = 12;
 
 template <class Type>
-class Array {
+class Array { // ERROR - .struct Array_RC redecl.*
 friend class Array_RC;
 public:
     Array(const Type *ar, int sz) { init(ar,sz); }
@@ -97,7 +97,7 @@ try_array( Array_RC<Type> &rc )
 main()
 {
     static int ia[10] = { 12, 7, 14, 9, 128, 17, 6, 3, 27, 5 };
-    Array_RC<int> iA(ia, 10);// ERROR - .struct Array_RC redecl.*
+    Array_RC<int> iA(ia, 10);// ERROR - instantiated from here
 
     cout << "template Array_RC class" << endl;
     try_array(iA);
diff --git a/gcc/testsuite/g++.old-deja/g++.other/dtor2.C b/gcc/testsuite/g++.old-deja/g++.other/dtor2.C
new file mode 100644 (file)
index 0000000..201068c
--- /dev/null
@@ -0,0 +1,13 @@
+// Build don't link:
+
+class K {
+public:
+  friend class C;
+
+private:
+  static K qwe;
+  K();
+  ~K();
+}; 
+
+K K::qwe;
index efb24b1..21065f1 100644 (file)
@@ -2,9 +2,9 @@
 
 template <class T = int> // ERROR - original definition
 struct S
-{
+{ // ERROR - redefinition of default arg
   template <class U = int>
   friend class S;
 };
 
-template struct S<int>; // ERROR - redefinition of default arg
+template struct S<int>; // ERROR - instantiated from here
index 888f1de..6dab744 100644 (file)
@@ -1,9 +1,9 @@
 // Build don't link: 
 
-template <class A> class B {
-  A a;
+template <class A> class B {    // ERROR - candidates
+  A a;                          
  public:
-  B(A&aa);                     // ERROR - 
+  B(A&aa);                     // ERROR - near match
   ~B();
 };
-static B<int> b_int (3);       // ERROR - 
+static B<int> b_int (3);       // ERROR - no matching function
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
new file mode 100644 (file)
index 0000000..d2eb4ce
--- /dev/null
@@ -0,0 +1,27 @@
+// Build don't link:
+
+template < class T > class A
+{
+public:
+  typedef typename T::myT anotherT; // ERROR - undefined type
+
+  anotherT t; // ERROR - undefined type 
+
+  A(anotherT _t) { // ERROR - undefined type
+    t=_t;
+  }
+
+  anotherT getT() {
+    return t;
+  }
+};
+
+class B : public A< B >
+{
+public:
+  typedef int myT;
+};
+
+int main() {
+  B b;
+}
index dd9e0e5..9414154 100644 (file)
@@ -17,7 +17,7 @@ inline istream& operator>>(istream& is, Empty& ) { return is;}
 
 template<class VertexType, class EdgeType>
 class Graph
-{
+{ // ERROR - candidates
   public:
     // public type interface
     typedef map<int, EdgeType > Successor;
index ae4fc66..d056e39 100644 (file)
@@ -1,11 +1,11 @@
 template<class T>
 struct A {
-  typedef T* iterator;
+  typedef T* iterator; // ERROR - pointer to reference
 public:
   A(){}
 };
 
 void f()
 {
-  A<int&> a;  // ERROR - pointer to reference
+  A<int&> a; // ERROR - instantiated from here
 }