* pt.c (instantiate_class_template): Don't try to figure out what
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Nov 1998 14:41:37 +0000 (14:41 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Nov 1998 14:41:37 +0000 (14:41 +0000)
specialization to use for a partial instantiation.  Correct
typos in a couple of comments.  Avoid calling uses_template_parms
multiple times.

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

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.pt/spec25.C [new file with mode: 0644]

index 7a7d3e1..ff7f563 100644 (file)
@@ -1,3 +1,10 @@
+1998-11-23  Mark Mitchell  <mark@markmitchell.com>
+
+       * pt.c (instantiate_class_template): Don't try to figure out what
+       specialization to use for a partial instantiation.  Correct
+       typos in a couple of comments.  Avoid calling uses_template_parms
+       multiple times.
+
 1998-11-23  Benjamin Kosnik  <bkoz@cygnus.com>
 
         * method.c (process_overload_item): Add call to
index f416239..c8ecd45 100644 (file)
@@ -4452,6 +4452,7 @@ instantiate_class_template (type)
 {
   tree template, args, pattern, t;
   tree typedecl;
+  int is_partial_instantiation;
 
   if (type == error_mark_node)
     return error_mark_node;
@@ -4465,29 +4466,52 @@ instantiate_class_template (type)
      argument coercion and such is simply lost.  */
   push_momentary ();
 
+  /* Figure out which template is being instantiated.  */
   template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
-  args = CLASSTYPE_TI_ARGS (type);
   my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
-  t = most_specialized_class (template, args);
 
-  if (t == error_mark_node)
+  /* Figure out which arguments are being used to do the
+     instantiation.  */
+  args = CLASSTYPE_TI_ARGS (type);
+  is_partial_instantiation = uses_template_parms (args);
+
+  if (is_partial_instantiation)
+    /* There's no telling which specialization is appropriate at this
+       point.  Since all peeking at the innards of this partial
+       instantiation are extensions (like the "implicit typename"
+       extension, which allows users to omit the keyword `typename' on
+       names that are declared as types in template base classes), we
+       are free to do what we please.
+
+       Trying to figure out which partial instantiation to use can
+       cause a crash.  (Some of the template arguments don't even have
+       types.)  So, we just use the most general version.  */
+    t = NULL_TREE;
+  else
     {
-      char *str = "candidates are:";
-      cp_error ("ambiguous class template instantiation for `%#T'", type);
-      for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
+      t = most_specialized_class (template, args);
+
+      if (t == error_mark_node)
        {
-         if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
-                                 args))
+         char *str = "candidates are:";
+         cp_error ("ambiguous class template instantiation for `%#T'", type);
+         for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; 
+              t = TREE_CHAIN (t))
            {
-             cp_error_at ("%s %+#T", str, TREE_TYPE (t));
-             str = "               ";
+             if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+                                     args))
+               {
+                 cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+                 str = "               ";
+               }
            }
+         TYPE_BEING_DEFINED (type) = 1;
+         type = error_mark_node;
+         goto end;
        }
-      TYPE_BEING_DEFINED (type) = 1;
-      type = error_mark_node;
-      goto end;
     }
-  else if (t)
+
+  if (t)
     pattern = TREE_TYPE (t);
   else
     pattern = TREE_TYPE (template);
@@ -4523,14 +4547,14 @@ instantiate_class_template (type)
        args = inner_args;
     }
 
-  if (pedantic && uses_template_parms (args))
+  if (pedantic && is_partial_instantiation)
     {
-      /* If there are still template parameters amongst the args, then
-        we can't instantiate the type; there's no telling whether or not one
-        of the template parameters might eventually be instantiated to some
-        value that results in a specialization being used.  We do the
-        type as complete so that, for example, declaring one of its
-        members to be a friend will not be rejected.  */
+      /* If this is a partial instantiation, then we can't instantiate
+        the type; there's no telling whether or not one of the
+        template parameters might eventually be instantiated to some
+        value that results in a specialization being used.  We do
+        mark the type as complete so that, for example, declaring one
+        of its members to be a friend will not be rejected.  */
       TYPE_SIZE (type) = integer_zero_node;
       goto end;
     }
@@ -4603,7 +4627,7 @@ instantiate_class_template (type)
   /* If this is a partial instantiation, don't tsubst anything.  We will
      only use this type for implicit typename, so the actual contents don't
      matter.  All that matters is whether a particular name is a type.  */
-  if (uses_template_parms (type))
+  if (is_partial_instantiation)
     {
       TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
       TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
@@ -7335,7 +7359,7 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
     return 0;
 
   /* If PARM uses template parameters, then we can't bail out here,
-     even in ARG == PARM, since we won't record unifications for the
+     even if ARG == PARM, since we won't record unifications for the
      template parameters.  We might need them if we're trying to
      figure out which of two things is more specialized.  */
   if (arg == parm && !uses_template_parms (parm))
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec25.C b/gcc/testsuite/g++.old-deja/g++.pt/spec25.C
new file mode 100644 (file)
index 0000000..884abf0
--- /dev/null
@@ -0,0 +1,15 @@
+// Build don't link:
+
+template <class T, int I>
+struct S {
+};
+
+template <int I>
+struct S <double, I> {
+};
+
+template <class T>
+void f ()
+{
+  S<double, T::x> s;
+}