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:
parent
848b92e1cc
commit
fbf1c34bfa
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
135
gcc/cp/pt.c
135
gcc/cp/pt.c
|
@ -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. */
|
||||
|
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue