decl.c (duplicate_decls): Always merge the old and new patterns for templates...
* decl.c (duplicate_decls): Always merge the old and new patterns for templates, regardless of whether or not the new one has DECL_INITIAL. Don't throw away specializations. Merge DECL_SAVED_TREE. * pt.c (tsubst_decl): Use the right pattern when calculating the complete args for a new template instance. (do_decl_instantiation): Fix typo in comment. (regenerate_decl_from_template): Deal with tricky friend template case. (instantiate_decl): Likewise. From-SVN: r21876
This commit is contained in:
parent
293bcdc970
commit
4d85e00e38
@ -1,3 +1,16 @@
|
||||
1998-08-20 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* decl.c (duplicate_decls): Always merge the old and new patterns
|
||||
for templates, regardless of whether or not the new one has
|
||||
DECL_INITIAL. Don't throw away specializations. Merge
|
||||
DECL_SAVED_TREE.
|
||||
* pt.c (tsubst_decl): Use the right pattern when calculating the
|
||||
complete args for a new template instance.
|
||||
(do_decl_instantiation): Fix typo in comment.
|
||||
(regenerate_decl_from_template): Deal with tricky friend template
|
||||
case.
|
||||
(instantiate_decl): Likewise.
|
||||
|
||||
Thu Aug 20 09:09:45 1998 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* init.c (build_builtin_delete_call): Add missing assemble_external
|
||||
|
@ -2982,17 +2982,15 @@ duplicate_decls (newdecl, olddecl)
|
||||
|
||||
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
||||
{
|
||||
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE)
|
||||
{
|
||||
if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
|
||||
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);
|
||||
DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
|
||||
}
|
||||
DECL_TEMPLATE_SPECIALIZATIONS (newdecl)
|
||||
= DECL_TEMPLATE_SPECIALIZATIONS (olddecl);
|
||||
if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
|
||||
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);
|
||||
DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
|
||||
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
|
||||
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
|
||||
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -3067,6 +3065,9 @@ duplicate_decls (newdecl, olddecl)
|
||||
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
|
||||
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
|
||||
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
|
||||
if (DECL_LANG_SPECIFIC (newdecl)
|
||||
&& DECL_LANG_SPECIFIC (olddecl))
|
||||
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
|
||||
}
|
||||
|
||||
/* Merge the section attribute.
|
||||
|
112
gcc/cp/pt.c
112
gcc/cp/pt.c
@ -4847,7 +4847,8 @@ tsubst_decl (t, args, type, in_decl)
|
||||
specialization, and the complete set of arguments used to
|
||||
specialize R. */
|
||||
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
|
||||
argvec = tsubst (DECL_TI_ARGS (t), args, in_decl);
|
||||
argvec = tsubst (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (gen_tmpl)),
|
||||
args, in_decl);
|
||||
|
||||
/* Check to see if we already have this specialization. */
|
||||
spec = retrieve_specialization (gen_tmpl, argvec);
|
||||
@ -7460,7 +7461,7 @@ do_decl_instantiation (declspecs, declarator, storage)
|
||||
else if (DECL_TEMPLATE_SPECIALIZATION (decl))
|
||||
/* [temp.spec]
|
||||
|
||||
No program shall both explicit instantiation and explicit
|
||||
No program shall both explicitly instantiate and explicitly
|
||||
specialize a template. */
|
||||
{
|
||||
cp_error ("explicit instantiation of `%#D' after", decl);
|
||||
@ -7649,6 +7650,9 @@ regenerate_decl_from_template (decl, tmpl)
|
||||
tree code_pattern;
|
||||
tree new_decl;
|
||||
tree gen_tmpl;
|
||||
tree subst_args;
|
||||
int args_depth;
|
||||
int parms_depth;
|
||||
int unregistered;
|
||||
|
||||
args = DECL_TI_ARGS (decl);
|
||||
@ -7667,15 +7671,51 @@ regenerate_decl_from_template (decl, tmpl)
|
||||
register_specialization for it. */
|
||||
my_friendly_assert (unregistered, 0);
|
||||
|
||||
/* Do the substitution to get the new declaration. */
|
||||
new_decl = tsubst (code_pattern, args, NULL_TREE);
|
||||
/* Do the substitution to get the new declaration. Normally, of
|
||||
course, we want the full set of ARGS. However, one peculiar case
|
||||
is code like this:
|
||||
|
||||
template <class T> struct S {
|
||||
template <class U> friend void f();
|
||||
};
|
||||
template <class U> friend void f() {}
|
||||
template S<int>;
|
||||
template void f<double>();
|
||||
|
||||
Here, the ARGS for the instantiation of will be {int, double}.
|
||||
But, we only need as many ARGS as there are levels of template
|
||||
parameters in CODE_PATTERN. We are careful not to get fooled
|
||||
into reducing the ARGS in situations like:
|
||||
|
||||
template <class T> struct S { template <class U> void f(U); }
|
||||
template <class T> template <> void S<T>::f(int) {}
|
||||
|
||||
which we can spot because the innermost template args for the
|
||||
CODE_PATTERN don't use any template parameters. */
|
||||
args_depth = TMPL_ARGS_DEPTH (args);
|
||||
parms_depth =
|
||||
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (code_pattern)));
|
||||
if (args_depth > parms_depth
|
||||
&& !DECL_TEMPLATE_SPECIALIZATION (code_pattern))
|
||||
{
|
||||
int i;
|
||||
|
||||
subst_args = make_temp_vec (parms_depth);
|
||||
for (i = 0; i < parms_depth; ++i)
|
||||
TREE_VEC_ELT (subst_args, i) =
|
||||
TREE_VEC_ELT (args, i + (args_depth - parms_depth));
|
||||
}
|
||||
else
|
||||
subst_args = args;
|
||||
|
||||
new_decl = tsubst (code_pattern, subst_args, NULL_TREE);
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
/* Set up DECL_INITIAL, since tsubst doesn't. */
|
||||
pushclass (DECL_CONTEXT (decl), 2);
|
||||
DECL_INITIAL (new_decl) =
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), subst_args,
|
||||
DECL_TI_TEMPLATE (decl));
|
||||
popclass (1);
|
||||
}
|
||||
@ -7747,16 +7787,60 @@ instantiate_decl (d)
|
||||
if (! push_tinst_level (d))
|
||||
return d;
|
||||
|
||||
for (td = tmpl;
|
||||
DECL_TEMPLATE_INSTANTIATION (td)
|
||||
/* This next clause handles friend templates defined inside
|
||||
class templates. The friend templates are not really
|
||||
instantiations from the point of view of the language, but
|
||||
they are instantiations from the point of view of the
|
||||
compiler. */
|
||||
|| (DECL_TEMPLATE_INFO (td) && !DECL_TEMPLATE_SPECIALIZATION (td));
|
||||
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
|
||||
for the instantiation. This is not always the most general
|
||||
template. Consider, for example:
|
||||
|
||||
template <class T>
|
||||
struct S { template <class U> void f();
|
||||
template <> void f<int>(); };
|
||||
|
||||
and an instantiation of S<double>::f<int>. We want TD to be the
|
||||
specialization S<T>::f<int>, not the more general S<T>::f<U>. */
|
||||
td = tmpl;
|
||||
for (td = tmpl;
|
||||
/* An instantiation cannot have a definition, so we need a
|
||||
more general template. */
|
||||
DECL_TEMPLATE_INSTANTIATION (td)
|
||||
/* We must also deal with friend templates. Given:
|
||||
|
||||
template <class T> struct S {
|
||||
template <class U> friend void f() {};
|
||||
};
|
||||
|
||||
S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
|
||||
so far as the language is concerned, but that's still
|
||||
where we get the pattern for the instantiation from. On
|
||||
ther hand, if the definition comes outside the class, say:
|
||||
|
||||
template <class T> struct S {
|
||||
template <class U> friend void f();
|
||||
};
|
||||
template <class U> friend void f() {}
|
||||
|
||||
we don't need to look any further. That's what the check for
|
||||
DECL_INITIAL is for. */
|
||||
|| (TREE_CODE (d) == FUNCTION_DECL
|
||||
&& DECL_TEMPLATE_INFO (td)
|
||||
&& !DECL_TEMPLATE_SPECIALIZATION (td)
|
||||
&& !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)));
|
||||
)
|
||||
td = DECL_TI_TEMPLATE (td);
|
||||
{
|
||||
/* The present template, TD, should not be a definition. If it
|
||||
were a definition, we should be using it! Note that we
|
||||
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);
|
||||
|
||||
/* Fetch the more general template. */
|
||||
td = DECL_TI_TEMPLATE (td);
|
||||
}
|
||||
|
||||
code_pattern = DECL_TEMPLATE_RESULT (td);
|
||||
|
||||
|
18
gcc/testsuite/g++.old-deja/g++.pt/friend30.C
Normal file
18
gcc/testsuite/g++.old-deja/g++.pt/friend30.C
Normal file
@ -0,0 +1,18 @@
|
||||
// Build don't link:
|
||||
|
||||
template <class T, class U>
|
||||
struct S {
|
||||
template <class X, class Y, class Z>
|
||||
friend X f(X, Y, Z);
|
||||
};
|
||||
|
||||
template <class X, class Y, class Z>
|
||||
X f(X x, Y, Z) {
|
||||
return x;
|
||||
}
|
||||
|
||||
template char f(char, long, short);
|
||||
template char* f(char*, long*, short*);
|
||||
template class S<int, double>;
|
||||
template class S<void*, double>;
|
||||
template double* f(double*, long*, short*);
|
Loading…
Reference in New Issue
Block a user