pt.c (redeclare_class_template): New function.

* pt.c (redeclare_class_template): New function.
	* cp_tree.h (redeclare_class_template): Declare it.
	* decl.c (xref_tag): Use it.

From-SVN: r18855
This commit is contained in:
Mark Mitchell 1998-03-27 13:23:03 +00:00 committed by Mark Mitchell
parent 7daa142bd6
commit 7fe6899fb7
6 changed files with 108 additions and 0 deletions

View File

@ -1,3 +1,9 @@
Fri Mar 27 13:22:18 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (redeclare_class_template): New function.
* cp_tree.h (redeclare_class_template): Declare it.
* decl.c (xref_tag): Use it.
Thu Mar 26 11:16:30 1998 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_over_call): Check IS_AGGR_TYPE, not

View File

@ -2457,6 +2457,7 @@ extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((void));
extern tree current_template_args PROTO((void));
extern tree push_template_decl PROTO((tree));
extern void redeclare_class_template PROTO((tree));
extern tree lookup_template_class PROTO((tree, tree, tree, tree));
extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));

View File

@ -10889,6 +10889,9 @@ xref_tag (code_type_node, name, binfo, globalize)
if (BINDING_VALUE (binding) == NULL_TREE)
BINDING_VALUE (binding) = TYPE_NAME (ref);
}
if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
redeclare_class_template (ref);
}
if (binfo)

View File

@ -1792,6 +1792,66 @@ push_template_decl (decl)
return DECL_TEMPLATE_RESULT (tmpl);
}
/* Called when a class template TYPE is redeclared, e.g.:
template <class T> struct S;
template <class T> struct S {}; */
void
redeclare_class_template (type)
tree type;
{
tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
tree tmpl_parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
tree parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
int i;
if (!PRIMARY_TEMPLATE_P (tmpl))
/* The type is nested in some template class. Nothing to worry
about here; there are no new template parameters for the nested
type. */
return;
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
cp_error_at ("previous declaration `%D'", tmpl);
cp_error ("used %d template parameter%s instead of %d",
TREE_VEC_LENGTH (tmpl_parms),
TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s",
TREE_VEC_LENGTH (parms));
return;
}
for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i)
{
tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
if (TREE_CODE (tmpl_parm) != TREE_CODE (parm))
{
cp_error_at ("template parameter `%#D'", tmpl_parm);
cp_error ("redeclared here as `%#D'", parm);
return;
}
if (tmpl_default != NULL_TREE && parm_default != NULL_TREE)
{
/* We have in [temp.param]:
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
cp_error ("redefinition of default argument for `%#D'", parm);
return;
}
if (parm_default != NULL_TREE)
/* Update the previous template parameters (which are the ones
that will really count) with the new default value. */
TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)) = parm_default;
}
}
/* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the

View File

@ -0,0 +1,16 @@
// Build don't link:
template <class T>
struct S;
template <class T = int>
struct S {};
template <class T>
struct S;
void f()
{
S<> s;
}

View File

@ -0,0 +1,22 @@
// Build don't link:
template <class T>
struct S1; // ERROR - previous declaration
template <class T, class U>
struct S1 {}; // ERROR - used 1 template parameter
template <class T = int>
struct S2;
template <class T = int>
struct S2; // ERROR - redefinition of default
template <class T> // ERROR - template parameter
struct S3;
template <int I>
struct S3; // ERROR - redeclared here
template <template <class T> class C>
struct S3; // ERROR - redeclared here