Commit fbf1c34b by Mark Mitchell Committed by Mark Mitchell

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
parent 848b92e1
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> 1998-11-16 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (cplus_expand_expr_stmt): Promote warning about naked * decl.c (cplus_expand_expr_stmt): Promote warning about naked
......
...@@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */
Usage of DECL_LANG_FLAG_?: Usage of DECL_LANG_FLAG_?:
0: DECL_ERROR_REPORTED (in VAR_DECL). 0: DECL_ERROR_REPORTED (in VAR_DECL).
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_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). 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
3: DECL_IN_AGGR_P. 3: DECL_IN_AGGR_P.
4: DECL_MAYBE_TEMPLATE. 4: DECL_MAYBE_TEMPLATE.
...@@ -1812,6 +1813,12 @@ extern int flag_new_for_scope; ...@@ -1812,6 +1813,12 @@ extern int flag_new_for_scope;
/* This function may be a guiding decl for a template. */ /* This function may be a guiding decl for a template. */
#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE) #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. */ /* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
......
...@@ -2989,9 +2989,6 @@ duplicate_decls (newdecl, olddecl) ...@@ -2989,9 +2989,6 @@ duplicate_decls (newdecl, olddecl)
DECL_TEMPLATE_RESULT (olddecl))) DECL_TEMPLATE_RESULT (olddecl)))
cp_error ("invalid redeclaration of %D", newdecl); cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)); 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) DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl), = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl)); DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
...@@ -3123,11 +3120,7 @@ duplicate_decls (newdecl, olddecl) ...@@ -3123,11 +3120,7 @@ duplicate_decls (newdecl, olddecl)
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl); DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (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_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
}
olddecl_friend = DECL_FRIEND_P (olddecl); olddecl_friend = DECL_FRIEND_P (olddecl);
} }
......
...@@ -831,15 +831,22 @@ register_specialization (spec, tmpl, args) ...@@ -831,15 +831,22 @@ register_specialization (spec, tmpl, args)
We transform the existing DECL in place so that We transform the existing DECL in place so that
any pointers to it become pointers to the any pointers to it become pointers to the
updated declaration. */ updated declaration.
duplicate_decls (spec, TREE_VALUE (s));
return TREE_VALUE (s); 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)) else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{ {
duplicate_decls (spec, TREE_VALUE (s)); duplicate_decls (spec, fn);
return TREE_VALUE (s); return fn;
} }
} }
} }
...@@ -4247,16 +4254,30 @@ tsubst_friend_function (decl, args) ...@@ -4247,16 +4254,30 @@ tsubst_friend_function (decl, args)
if (DECL_NAMESPACE_SCOPE_P (new_friend)) if (DECL_NAMESPACE_SCOPE_P (new_friend))
{ {
tree old_decl; 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) if (TREE_CODE (new_friend) == TEMPLATE_DECL)
{
/* This declaration is a `primary' template. */ /* This declaration is a `primary' template. */
DECL_PRIMARY_TEMPLATE (new_friend) = new_friend; DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
/* We must save the DECL_TI_ARGS for NEW_FRIEND here because new_friend_is_defn
pushdecl may call duplicate_decls which will free NEW_FRIEND = DECL_INITIAL (DECL_RESULT (new_friend)) != NULL_TREE;
if possible. */ new_friend_result_template_info
new_friend_args = DECL_TI_ARGS (new_friend); = 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;
}
old_decl = pushdecl_namespace_level (new_friend); old_decl = pushdecl_namespace_level (new_friend);
if (old_decl != new_friend) if (old_decl != new_friend)
...@@ -4295,13 +4316,31 @@ tsubst_friend_function (decl, args) ...@@ -4295,13 +4316,31 @@ tsubst_friend_function (decl, args)
when `C<int>' is instantiated. Now, `f(int)' is defined when `C<int>' is instantiated. Now, `f(int)' is defined
in the class. */ in the class. */
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
{
/* 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;
if (TREE_CODE (old_decl) != TEMPLATE_DECL) if (TREE_CODE (old_decl) != TEMPLATE_DECL)
/* duplicate_decls will take care of this case. */ /* duplicate_decls will take care of this case. */
; ;
else else
{ {
tree 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); for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
t != NULL_TREE; t != NULL_TREE;
t = TREE_CHAIN (t)) t = TREE_CHAIN (t))
...@@ -4327,6 +4366,7 @@ tsubst_friend_function (decl, args) ...@@ -4327,6 +4366,7 @@ tsubst_friend_function (decl, args)
DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE; DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
} }
} }
}
/* The information from NEW_FRIEND has been merged into OLD_DECL /* The information from NEW_FRIEND has been merged into OLD_DECL
by duplicate_decls. */ by duplicate_decls. */
...@@ -5312,7 +5352,6 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5312,7 +5352,6 @@ tsubst_decl (t, args, type, in_decl)
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t); DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
DECL_MAIN_VARIANT (r) = r; DECL_MAIN_VARIANT (r) = r;
DECL_RESULT (r) = NULL_TREE; DECL_RESULT (r) = NULL_TREE;
DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0; TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t); TREE_PUBLIC (r) = TREE_PUBLIC (t);
...@@ -8285,9 +8324,13 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -8285,9 +8324,13 @@ regenerate_decl_from_template (decl, tmpl)
} }
if (TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */ new decl. */
DECL_INITIAL (new_decl) = error_mark_node; 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 /* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most before, even though tsubst sets DECL_TI_TEMPLATE up as the most
...@@ -8303,9 +8346,6 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -8303,9 +8346,6 @@ regenerate_decl_from_template (decl, tmpl)
/* Call duplicate decls to merge the old and new declarations. */ /* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl); duplicate_decls (new_decl, decl);
if (TREE_CODE (decl) == FUNCTION_DECL)
DECL_INITIAL (new_decl) = NULL_TREE;
/* Now, re-register the specialization. */ /* Now, re-register the specialization. */
register_specialization (decl, gen_tmpl, args); register_specialization (decl, gen_tmpl, args);
} }
...@@ -8332,8 +8372,7 @@ instantiate_decl (d) ...@@ -8332,8 +8372,7 @@ instantiate_decl (d)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0); || TREE_CODE (d) == VAR_DECL, 0);
if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d)) if (DECL_TEMPLATE_INSTANTIATED (d))
|| (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d)))
/* D has already been instantiated. It might seem reasonable to /* D has already been instantiated. It might seem reasonable to
check whether or not D is an explict instantiation, and, if so, check whether or not D is an explict instantiation, and, if so,
stop here. But when an explicit instantiation is deferred stop here. But when an explicit instantiation is deferred
...@@ -8398,9 +8437,6 @@ instantiate_decl (d) ...@@ -8398,9 +8437,6 @@ instantiate_decl (d)
cannot restructure the loop to just keep going until we find cannot restructure the loop to just keep going until we find
a template with a definition, since that might go too far if a template with a definition, since that might go too far if
a specialization was declared, but not defined. */ 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 my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
&& !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (td))), && !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (td))),
0); 0);
...@@ -8483,6 +8519,7 @@ instantiate_decl (d) ...@@ -8483,6 +8519,7 @@ instantiate_decl (d)
} }
regenerate_decl_from_template (d, td); regenerate_decl_from_template (d, td);
DECL_TEMPLATE_INSTANTIATED (d) = 1;
/* We already set the file and line above. Reset them now in case /* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */ they changed as a result of calling regenerate_decl_from_template. */
......
// 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;
...@@ -13,7 +13,7 @@ class H{ ...@@ -13,7 +13,7 @@ class H{
public: public:
#endif #endif
template<template<class, class> class Caster, typename Source> 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 #ifndef OK
template <typename Target, typename Source> template <typename Target, typename Source>
...@@ -26,10 +26,10 @@ template <class, class> class caster; ...@@ -26,10 +26,10 @@ template <class, class> class caster;
template <typename Target, typename Source> template <typename Target, typename Source>
H<Target> foo(const H<Source>& s){ 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(){ int main(){
H<int> i; H<int> i;
foo<const int>(i); // gets bogus error - instantiated from here - XFAIL *-*-* foo<const int>(i);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment