re PR c++/24791 (ICE on invalid instantiation of template's static member)
authorJason Merrill <jason@redhat.com>
Fri, 26 Oct 2007 19:54:10 +0000 (15:54 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 26 Oct 2007 19:54:10 +0000 (15:54 -0400)
        PR c++/24791
        * pt.c (get_template_info): New fn.
        (template_class_depth): Use it.
        (push_template_decl_real): Check that the template args of the
        definition match the args of the previous declaration.

From-SVN: r129660

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/error33.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/crash11.C

index 99a2bc57538b8c75d84559bcbed7edc2b969a77d..0ef16bf5de278370ec72520f1540e1b6ffafd987 100644 (file)
@@ -1,3 +1,11 @@
+2007-10-26  Jason Merrill  <jason@redhat.com>
+
+       PR c++/24791
+       * pt.c (get_template_info): New fn.
+       (template_class_depth): Use it.
+       (push_template_decl_real): Check that the template args of the 
+       definition match the args of the previous declaration.
+
 2007-10-26  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/31988
index bb02692a07ad6541dbb87be752a203ffd43b219a..f57f2f9abd471f7b65032fc08cc70d65ac21f777 100644 (file)
@@ -4437,6 +4437,7 @@ extern bool uses_parameter_packs                (tree);
 extern bool template_parameter_pack_p           (const_tree);
 extern tree make_pack_expansion                 (tree);
 extern bool check_for_bare_parameter_packs      (tree);
+extern tree get_template_info                  (tree);
 extern int template_class_depth                        (tree);
 extern int is_specialization_of                        (tree, tree);
 extern bool is_specialization_of_friend                (tree, tree);
index a54e90d6fa723bfb9ca9b8bf956146f3e6ce1717..9193f487f9021cbdec03e1777560c045b4be7715 100644 (file)
@@ -263,6 +263,25 @@ finish_member_template_decl (tree decl)
   return error_mark_node;
 }
 
+/* Return the template info node corresponding to T, whatever T is.  */
+
+tree
+get_template_info (tree t)
+{
+  tree tinfo = NULL_TREE;
+
+  if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+    tinfo = DECL_TEMPLATE_INFO (t);
+
+  if (!tinfo && TREE_CODE (t) == TYPE_DECL)
+    t = TREE_TYPE (t);
+
+  if (TAGGED_TYPE_P (t))
+    tinfo = TYPE_TEMPLATE_INFO (t);
+
+  return tinfo;
+}
+
 /* Returns the template nesting level of the indicated class TYPE.
 
    For example, in:
@@ -291,20 +310,11 @@ template_class_depth (tree type)
        type = (TREE_CODE (type) == FUNCTION_DECL)
         ? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
     {
-      if (TREE_CODE (type) != FUNCTION_DECL)
-       {
-         if (CLASSTYPE_TEMPLATE_INFO (type)
-             && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
-             && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
-           ++depth;
-       }
-      else
-       {
-         if (DECL_TEMPLATE_INFO (type)
-             && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
-             && uses_template_parms (DECL_TI_ARGS (type)))
-           ++depth;
-       }
+      tree tinfo = get_template_info (type);
+
+      if (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))
+         && uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo))))
+       ++depth;
     }
 
   return depth;
@@ -3866,27 +3876,15 @@ push_template_decl_real (tree decl, bool is_friend)
     {
       tree a, t, current, parms;
       int i;
+      tree tinfo = get_template_info (decl);
 
-      if (TREE_CODE (decl) == TYPE_DECL)
-       {
-         if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
-              || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
-             && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
-             && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
-           tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
-         else
-           {
-             error ("%qD does not declare a template type", decl);
-             return decl;
-           }
-       }
-      else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))
+      if (!tinfo)
        {
          error ("template definition of non-template %q#D", decl);
          return decl;
        }
-      else
-       tmpl = DECL_TI_TEMPLATE (decl);
+
+      tmpl = TI_TEMPLATE (tinfo);
 
       if (DECL_FUNCTION_TEMPLATE_P (tmpl)
          && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
@@ -3946,9 +3944,6 @@ push_template_decl_real (tree decl, bool is_friend)
                return error_mark_node;
              }
 
-           /* Perhaps we should also check that the parms are used in the
-              appropriate qualifying scopes in the declarator?  */
-
            if (current == decl)
              current = ctx;
            else
@@ -3956,6 +3951,22 @@ push_template_decl_real (tree decl, bool is_friend)
                         ? TYPE_CONTEXT (current)
                         : DECL_CONTEXT (current));
          }
+
+      /* Check that the parms are used in the appropriate qualifying scopes
+        in the declarator.  */
+      if (!comp_template_args
+         (TI_ARGS (tinfo),
+          TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl)))))
+       {
+         error ("\
+template arguments to %qD do not match original template %qD",
+                decl, DECL_TEMPLATE_RESULT (tmpl));
+         if (!uses_template_parms (TI_ARGS (tinfo)))
+           inform ("use template<> for an explicit specialization");
+         /* Avoid crash in import_export_decl.  */
+         DECL_INTERFACE_KNOWN (decl) = 1;
+         return error_mark_node;
+       }
     }
 
   DECL_TEMPLATE_RESULT (tmpl) = decl;
diff --git a/gcc/testsuite/g++.dg/template/error33.C b/gcc/testsuite/g++.dg/template/error33.C
new file mode 100644 (file)
index 0000000..e1ac822
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/24791
+
+template<int> struct A
+{
+    static int i;
+    A() { ++i; }
+};
+
+template<int> int A<0>::i(0);  // { dg-error "template" }
+
+A<0> a;
index be83f5abe7b679da947b7c09d6567cb13f5eaf38..5f372d3a311053ad15c0337ea063554f5c0de5a9 100644 (file)
@@ -8,6 +8,6 @@ class A
 };
 
 
-template <class j> class A::A_impl // { dg-error "does not declare a template" }
+template <class j> class A::A_impl // { dg-error "non-template" }
 {
 };