cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.

* cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.
	* decl.c (duplicate_decls): Remove special-case code to deal with
	template friends, and just do the obvious thing.
	* pt.c (register_specialization): Tweak for clarity, and also to
	clear DECL_INITIAL for an instantiation before it is merged with a
	specialization.
	(check_explicit_specialization): Fix indentation.
	(tsubst_friend_function): Handle both definitions in friend
	declaration and outside friend declarations.
	(tsubst_decl): Don't clear DECL_INITIAL for an instantiation.
	(regenerate_decl_from_template): Tweak accordingly.
	(instantiate_decl): Likewise.

From-SVN: r23674
This commit is contained in:
Mark Mitchell 1998-11-16 08:34:38 +00:00 committed by Mark Mitchell
parent 848b92e1cc
commit fbf1c34bfa
6 changed files with 124 additions and 60 deletions

View File

@ -1,3 +1,18 @@
1998-11-16 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.
* decl.c (duplicate_decls): Remove special-case code to deal with
template friends, and just do the obvious thing.
* pt.c (register_specialization): Tweak for clarity, and also to
clear DECL_INITIAL for an instantiation before it is merged with a
specialization.
(check_explicit_specialization): Fix indentation.
(tsubst_friend_function): Handle both definitions in friend
declaration and outside friend declarations.
(tsubst_decl): Don't clear DECL_INITIAL for an instantiation.
(regenerate_decl_from_template): Tweak accordingly.
(instantiate_decl): Likewise.
1998-11-16 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (cplus_expand_expr_stmt): Promote warning about naked

View File

@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */
Usage of DECL_LANG_FLAG_?:
0: DECL_ERROR_REPORTED (in VAR_DECL).
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
3: DECL_IN_AGGR_P.
4: DECL_MAYBE_TEMPLATE.
@ -1812,6 +1813,12 @@ extern int flag_new_for_scope;
/* This function may be a guiding decl for a template. */
#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
/* Nonzero if this VAR_DECL or FUNCTION_DECL has already been
instantiated, i.e. its definition has been generated from the
pattern given in the the template. */
#define DECL_TEMPLATE_INSTANTIATED(NODE) DECL_LANG_FLAG_1(NODE)
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)

View File

@ -2989,9 +2989,6 @@ duplicate_decls (newdecl, olddecl)
DECL_TEMPLATE_RESULT (olddecl)))
cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
if (DECL_TEMPLATE_INFO (newdecl))
DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
@ -3123,11 +3120,7 @@ duplicate_decls (newdecl, olddecl)
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
{
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
}
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
}

View File

@ -831,15 +831,22 @@ register_specialization (spec, tmpl, args)
We transform the existing DECL in place so that
any pointers to it become pointers to the
updated declaration. */
duplicate_decls (spec, TREE_VALUE (s));
return TREE_VALUE (s);
updated declaration.
If there was a definition for the template, but
not for the specialization, we want this to
look as if there is no definition, and vice
versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn);
return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
duplicate_decls (spec, TREE_VALUE (s));
return TREE_VALUE (s);
duplicate_decls (spec, fn);
return fn;
}
}
}
@ -1369,7 +1376,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
/* This is not really a declaration of a specialization.
It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
SET_DECL_IMPLICIT_INSTANTIATION (decl);
/* Register this specialization so that we can find it
again. */
@ -4247,16 +4254,30 @@ tsubst_friend_function (decl, args)
if (DECL_NAMESPACE_SCOPE_P (new_friend))
{
tree old_decl;
tree new_friend_args;
tree new_friend_template_info;
tree new_friend_result_template_info;
int new_friend_is_defn;
/* We must save some information from NEW_FRIEND before calling
duplicate decls since that function will free NEW_FRIEND if
possible. */
new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
if (TREE_CODE (new_friend) == TEMPLATE_DECL)
/* This declaration is a `primary' template. */
DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
{
/* This declaration is a `primary' template. */
DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
new_friend_is_defn
= DECL_INITIAL (DECL_RESULT (new_friend)) != NULL_TREE;
new_friend_result_template_info
= DECL_TEMPLATE_INFO (DECL_RESULT (new_friend));
}
else
{
new_friend_is_defn = DECL_INITIAL (new_friend) != NULL_TREE;
new_friend_result_template_info = NULL_TREE;
}
/* We must save the DECL_TI_ARGS for NEW_FRIEND here because
pushdecl may call duplicate_decls which will free NEW_FRIEND
if possible. */
new_friend_args = DECL_TI_ARGS (new_friend);
old_decl = pushdecl_namespace_level (new_friend);
if (old_decl != new_friend)
@ -4295,36 +4316,55 @@ tsubst_friend_function (decl, args)
when `C<int>' is instantiated. Now, `f(int)' is defined
in the class. */
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
/* duplicate_decls will take care of this case. */
if (!new_friend_is_defn)
/* On the other hand, if the in-class declaration does
*not* provide a definition, then we don't want to alter
existing definitions. We can just leave everything
alone. */
;
else
else
{
tree t;
/* Overwrite whatever template info was there before, if
any, with the new template information pertaining to
the declaration. */
DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
t != NULL_TREE;
t = TREE_CHAIN (t))
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
/* duplicate_decls will take care of this case. */
;
else
{
tree spec = TREE_VALUE (t);
tree t;
tree new_friend_args;
DECL_TEMPLATE_INFO (DECL_RESULT (old_decl))
= new_friend_result_template_info;
new_friend_args = TI_ARGS (new_friend_template_info);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
t != NULL_TREE;
t = TREE_CHAIN (t))
{
tree spec = TREE_VALUE (t);
DECL_TI_ARGS (spec)
= add_outermost_template_args (new_friend_args,
DECL_TI_ARGS (spec));
DECL_TI_ARGS (spec)
= copy_to_permanent (DECL_TI_ARGS (spec));
}
DECL_TI_ARGS (spec)
= add_outermost_template_args (new_friend_args,
DECL_TI_ARGS (spec));
DECL_TI_ARGS (spec)
= copy_to_permanent (DECL_TI_ARGS (spec));
}
/* Now, since specializations are always supposed to
hang off of the most general template, we must move
them. */
t = most_general_template (old_decl);
if (t != old_decl)
{
DECL_TEMPLATE_SPECIALIZATIONS (t)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
/* Now, since specializations are always supposed to
hang off of the most general template, we must move
them. */
t = most_general_template (old_decl);
if (t != old_decl)
{
DECL_TEMPLATE_SPECIALIZATIONS (t)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
}
}
}
@ -5312,7 +5352,6 @@ tsubst_decl (t, args, type, in_decl)
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
DECL_MAIN_VARIANT (r) = r;
DECL_RESULT (r) = NULL_TREE;
DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
@ -8285,9 +8324,13 @@ regenerate_decl_from_template (decl, tmpl)
}
if (TREE_CODE (decl) == FUNCTION_DECL)
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
DECL_INITIAL (new_decl) = error_mark_node;
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
DECL_INITIAL (new_decl) = error_mark_node;
/* And don't complain about a duplicate definition. */
DECL_INITIAL (decl) = NULL_TREE;
}
/* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most
@ -8303,9 +8346,6 @@ regenerate_decl_from_template (decl, tmpl)
/* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl);
if (TREE_CODE (decl) == FUNCTION_DECL)
DECL_INITIAL (new_decl) = NULL_TREE;
/* Now, re-register the specialization. */
register_specialization (decl, gen_tmpl, args);
}
@ -8332,8 +8372,7 @@ instantiate_decl (d)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0);
if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d))
|| (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d)))
if (DECL_TEMPLATE_INSTANTIATED (d))
/* D has already been instantiated. It might seem reasonable to
check whether or not D is an explict instantiation, and, if so,
stop here. But when an explicit instantiation is deferred
@ -8398,9 +8437,6 @@ instantiate_decl (d)
cannot restructure the loop to just keep going until we find
a template with a definition, since that might go too far if
a specialization was declared, but not defined. */
my_friendly_assert (!(TREE_CODE (d) == FUNCTION_DECL
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (td))),
0);
my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
&& !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (td))),
0);
@ -8483,6 +8519,7 @@ instantiate_decl (d)
}
regenerate_decl_from_template (d, td);
DECL_TEMPLATE_INSTANTIATED (d) = 1;
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */

View File

@ -0,0 +1,12 @@
// Build don't link:
template <class T>
void f(T) {} // ERROR - previously defined here
template <class U>
struct S {
template <class T>
friend void f(T) {} // ERROR - redeclaration
};
S<int> si;

View File

@ -13,7 +13,7 @@ class H{
public:
#endif
template<template<class, class> class Caster, typename Source>
static H<Type> cast(const H<Source>& s); // gets bogus error - candidate - XFAIL *-*-*
static H<Type> cast(const H<Source>& s);
#ifndef OK
template <typename Target, typename Source>
@ -26,10 +26,10 @@ template <class, class> class caster;
template <typename Target, typename Source>
H<Target> foo(const H<Source>& s){
return H<Target>::template cast<caster, Source>(s); // gets bogus error - no match - XFAIL *-*-*
return H<Target>::template cast<caster, Source>(s);
}
int main(){
H<int> i;
foo<const int>(i); // gets bogus error - instantiated from here - XFAIL *-*-*
foo<const int>(i);
}