diff options
author | Mark Mitchell <mark@markmitchell.com> | 1998-11-16 08:34:38 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-11-16 08:34:38 +0000 |
commit | fbf1c34bfa83a4b08f9ee8651250cd989d0bd0ba (patch) | |
tree | 4e2640645217b40b287d5f8c413c905bb4a702c8 | |
parent | 848b92e1cc58303988dadd22623b904697084092 (diff) | |
download | gcc-fbf1c34bfa83a4b08f9ee8651250cd989d0bd0ba.zip gcc-fbf1c34bfa83a4b08f9ee8651250cd989d0bd0ba.tar.gz gcc-fbf1c34bfa83a4b08f9ee8651250cd989d0bd0ba.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 9 | ||||
-rw-r--r-- | gcc/cp/pt.c | 141 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/friend36.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp53.C | 6 |
6 files changed, 127 insertions, 63 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 86503ae..bbd8664 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a6e2e2d..8cf5594 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 33c44494..a9779f9 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fb5bb54..655a72b 100644 --- a/gcc/cp/pt.c +++ b/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; - - for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl); - t != NULL_TREE; - t = TREE_CHAIN (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; + + 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)); - } - - /* 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; + 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; + } } } @@ -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. */ diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend36.C b/gcc/testsuite/g++.old-deja/g++.pt/friend36.C new file mode 100644 index 0000000..4a9042a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend36.C @@ -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; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp53.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp53.C index 694635d..e5e87b4 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ttp53.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp53.C @@ -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); } |