This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/24791
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 26 Oct 2007 15:46:15 -0400
- Subject: C++ PATCH for c++/24791
Another of our most-reported bugs: This is a bug where we were crashing
when people try to do an explicit specialization with the same template
header as the template rather than just "template<>". Now we give a
more helpful error message.
Yes, I've just been complaining about giving too high priority to
ice-on-invalid bugs, but this one seems higher priority because of the
number of duplicate reports.
Tested x86_64-pc-linux-gnu, applied to trunk.
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.
Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h (revision 129643)
--- cp/cp-tree.h (working copy)
*************** extern bool uses_parameter_packs
*** 4440,4445 ****
--- 4440,4446 ----
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: cp/pt.c
===================================================================
*** cp/pt.c (revision 129643)
--- cp/pt.c (working copy)
*************** finish_member_template_decl (tree decl)
*** 263,268 ****
--- 263,287 ----
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:
*************** template_class_depth (tree type)
*** 291,310 ****
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;
! }
}
return depth;
--- 310,320 ----
type = (TREE_CODE (type) == FUNCTION_DECL)
? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
{
! 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;
*************** push_template_decl_real (tree decl, bool
*** 3866,3892 ****
{
tree a, t, current, parms;
int i;
! 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))
{
error ("template definition of non-template %q#D", decl);
return decl;
}
! else
! tmpl = DECL_TI_TEMPLATE (decl);
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
--- 3876,3890 ----
{
tree a, t, current, parms;
int i;
+ tree tinfo = get_template_info (decl);
! if (!tinfo)
{
error ("template definition of non-template %q#D", decl);
return decl;
}
!
! tmpl = TI_TEMPLATE (tinfo);
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
*************** push_template_decl_real (tree decl, bool
*** 3946,3954 ****
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
--- 3944,3949 ----
*************** push_template_decl_real (tree decl, bool
*** 3956,3961 ****
--- 3951,3972 ----
? 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;
Index: testsuite/g++.old-deja/g++.pt/crash11.C
===================================================================
*** testsuite/g++.old-deja/g++.pt/crash11.C (revision 129643)
--- testsuite/g++.old-deja/g++.pt/crash11.C (working copy)
*************** class A
*** 8,13 ****
};
! template <class j> class A::A_impl // { dg-error "does not declare a template" }
{
};
--- 8,13 ----
};
! template <class j> class A::A_impl // { dg-error "non-template" }
{
};
Index: testsuite/g++.dg/template/error33.C
===================================================================
*** testsuite/g++.dg/template/error33.C (revision 0)
--- testsuite/g++.dg/template/error33.C (revision 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;