From 6c30752f0916390d06be4a7e46d8aea7407dd4c1 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 5 Sep 1998 20:14:21 +0000 Subject: [PATCH] cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove. * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove. * class.c (finish_struct): Remove hackery to deal with explicit specializations in class scope. * decl.c (grokfndecl): Improve error-recovery. * decl2.c (grokfield): Likewise. * pt.c (check_specialization_scope): New function. (begin_specialization): Call it. (process_partial_specialization): New function, split out from push_template_decl. Check partial specializations more stringently. (push_template_decl): Call it. (check_explicit_specialization): Don't attempt to handle explicit specializations in class scope. (template_parm_data): Document. Add current_arg and arg_uses_template_parms. (mark_template_parm): Set it. (tsubst_arg_types): Remove unused variable. * semantics.c (begin_class_definition): Tweak. From-SVN: r22271 --- gcc/cp/ChangeLog | 21 ++ gcc/cp/class.c | 36 -- gcc/cp/cp-tree.h | 6 - gcc/cp/decl.c | 18 +- gcc/cp/decl2.c | 4 +- gcc/cp/pt.c | 347 +++++++++++++----- gcc/cp/semantics.c | 2 +- .../g++.old-deja/g++.pt/explicit12.C | 8 +- .../g++.old-deja/g++.pt/explicit13.C | 7 +- .../g++.old-deja/g++.pt/explicit35.C | 6 +- gcc/testsuite/g++.old-deja/g++.pt/memclass7.C | 7 +- gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C | 3 - gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C | 3 - gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/spec10.C | 13 +- gcc/testsuite/g++.old-deja/g++.pt/spec11.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/spec12.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/spec13.C | 13 +- gcc/testsuite/g++.old-deja/g++.pt/spec15.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/spec20.C | 11 + gcc/testsuite/g++.old-deja/g++.pt/spec21.C | 16 + gcc/testsuite/g++.old-deja/g++.pt/spec22.C | 15 + gcc/testsuite/g++.old-deja/g++.pt/spec6.C | 14 +- 23 files changed, 373 insertions(+), 193 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/spec20.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/spec21.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/spec22.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0beacd2e8ed..c092ea215c1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +1998-09-05 Mark Mitchell + + * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove. + * class.c (finish_struct): Remove hackery to deal with explicit + specializations in class scope. + * decl.c (grokfndecl): Improve error-recovery. + * decl2.c (grokfield): Likewise. + * pt.c (check_specialization_scope): New function. + (begin_specialization): Call it. + (process_partial_specialization): New function, split out from + push_template_decl. Check partial specializations more + stringently. + (push_template_decl): Call it. + (check_explicit_specialization): Don't attempt to handle explicit + specializations in class scope. + (template_parm_data): Document. Add current_arg and + arg_uses_template_parms. + (mark_template_parm): Set it. + (tsubst_arg_types): Remove unused variable. + * semantics.c (begin_class_definition): Tweak. + 1998-09-04 Mark Mitchell * inc/typeinfo (type_info::type_info(const char*)): Make diff --git a/gcc/cp/class.c b/gcc/cp/class.c index bcdf9571d47..173c69a2830 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4148,8 +4148,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) { tree fields = NULL_TREE; tree *tail = &TYPE_METHODS (t); - tree specializations = NULL_TREE; - tree *specialization_tail = &specializations; tree name = TYPE_NAME (t); tree x, last_x = NULL_TREE; tree access; @@ -4259,19 +4257,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) if (last_x) TREE_CHAIN (last_x) = next_x; - if (DECL_TEMPLATE_SPECIALIZATION (x)) - /* We don't enter the specialization into the class - method vector since specializations don't affect - overloading. Instead we keep track of the - specializations, and process them after the method - vector is complete. */ - { - *specialization_tail = x; - specialization_tail = &TREE_CHAIN (x); - TREE_CHAIN (x) = NULL_TREE; - continue; - } - /* Link x onto end of TYPE_METHODS. */ *tail = x; tail = &TREE_CHAIN (x); @@ -4359,27 +4344,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) t = finish_struct_1 (t, warn_anon); TYPE_BEING_DEFINED (t) = 0; - - /* Now, figure out which member templates we're specializing. */ - for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x)) - { - int pending_specialization; - - pending_specialization - = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)); - check_explicit_specialization - (lookup_template_function (DECL_NAME (x), DECL_TI_ARGS (x)), - x, 0, 1 | (8 * pending_specialization)); - TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)) = 0; - - /* Now, the assembler name will be correct for fn, so we - make its RTL. */ - DECL_RTL (x) = 0; - make_decl_rtl (x, NULL_PTR, 1); - DECL_RTL (DECL_TI_TEMPLATE (x)) = 0; - make_decl_rtl (DECL_TI_TEMPLATE (x), NULL_PTR, 1); - } - if (current_class_type) popclass (0); else diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8bf6c5c8621..3c3a8588139 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */ (TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out). 1: IDENTIFIER_VIRTUAL_P. TI_PENDING_TEMPLATE_FLAG. - TI_PENDING_SPECIALIZATION_FLAG. TEMPLATE_PARMS_FOR_INLINE. DELETE_EXPR_USE_VEC (in DELETE_EXPR). (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out). @@ -1267,11 +1266,6 @@ struct lang_decl #define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE)) #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) -/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates - that the template is a specialization of a member template, but - that we don't yet know which one. */ -#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) - /* The TEMPLATE_DECL instantiated or specialized by NODE. This TEMPLATE_DECL will be the immediate parent, not the most general template. For example, in: diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 75538c4a415..42748ff1516 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8016,6 +8016,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, template_count, 2 * (funcdef_flag != 0) + 4 * (friendp != 0)); + if (decl == error_mark_node) + return error_mark_node; if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl)) && check) @@ -8063,6 +8065,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, template_count, 2 * (funcdef_flag != 0) + 4 * (friendp != 0)); + if (decl == error_mark_node) + return error_mark_node; + if (ctype != NULL_TREE && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl)) && check) @@ -10392,10 +10397,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) if (decl && DECL_NAME (decl)) { if (template_class_depth (current_class_type) == 0) - decl - = check_explicit_specialization - (declarator, decl, - template_count, 2 * (funcdef_flag != 0) + 4); + { + decl + = check_explicit_specialization + (declarator, decl, + template_count, 2 * (funcdef_flag != 0) + 4); + if (decl == error_mark_node) + return error_mark_node; + } + t = do_friend (ctype, declarator, decl, last_function_parms, flags, quals, funcdef_flag); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c01bda29c43..be8689ce189 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1606,8 +1606,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) init = NULL_TREE; value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE); - if (! value) - return value; /* friend or constructor went bad. */ + if (! value || value == error_mark_node) + return NULL_TREE; /* friend or constructor went bad. */ /* Pass friendly classes back. */ if (TREE_CODE (value) == VOID_TYPE) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b27621b89d0..04c9fd65fda 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -127,6 +127,8 @@ static int template_class_depth_real PROTO((tree, int)); static tree tsubst_aggr_type PROTO((tree, tree, tree, int)); static tree tsubst_decl PROTO((tree, tree, tree, tree)); static tree tsubst_arg_types PROTO((tree, tree, tree)); +static void check_specialization_scope PROTO((void)); +static tree process_partial_specialization PROTO((tree)); /* We use TREE_VECs to hold template arguments. If there is only one level of template arguments, then the TREE_VEC contains the @@ -575,12 +577,44 @@ begin_template_parm_list () note_template_header (0); } +/* This routine is called when a specialization is declared. If it is + illegal to declare a specialization here, an error is reported. */ + +void +check_specialization_scope () +{ + tree scope = current_scope (); + /* [temp.expl.spec] + + An explicit specialization shall be declared in the namespace of + which the template is a member, or, for member templates, in the + namespace of which the enclosing class or enclosing class + template is a member. An explicit specialization of a member + function, member class or static data member of a class template + shall be declared in the namespace of which the class template + is a member. */ + if (scope && TREE_CODE (scope) != NAMESPACE_DECL) + cp_error ("explicit specialization in non-namespace scope `%D'", + scope); + /* [temp.expl.spec] + + In an explicit specialization declaration for a member of a class + template or a member template that appears in namespace scope, + the member template and some of its enclosing class templates may + remain unspecialized, except that the declaration shall not + explicitly specialize a class member template if its enclosing + class templates are not explicitly specialized as well. */ + if (current_template_parms) + cp_error ("enclosing class templates are not explicit specialized"); +} + /* We've just seen template <>. */ void begin_specialization () { note_template_header (1); + check_specialization_scope (); } /* Called at then end of processing a declaration preceeded by @@ -1209,17 +1243,10 @@ check_explicit_specialization (declarator, decl, template_count, flags) if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype)) { if (!explicit_instantiation) - { - /* Since finish_struct_1 has not been called yet, we - can't call lookup_fnfields. We note that this - template is a specialization, and proceed, letting - finish_struct fix this up later. */ - tree ti = perm_tree_cons (NULL_TREE, - TREE_OPERAND (declarator, 1), - NULL_TREE); - TI_PENDING_SPECIALIZATION_FLAG (ti) = 1; - DECL_TEMPLATE_INFO (decl) = ti; - } + /* A specialization in class scope. This is illegal, + but the error will already have been flagged by + check_specialization_scope. */ + return error_mark_node; else /* It's not legal to write an explicit instantiation in class scope, e.g.: @@ -1759,8 +1786,23 @@ build_template_decl (decl, parms) struct template_parm_data { + /* The level of the template parameters we are currently + processing. */ int level; + + /* The index of the specialization argument we are currently + processing. */ + int current_arg; + + /* An array whose size is the number of template parameters. The + elements are non-zero if the parameter has been used in any one + of the arguments processed so far. */ int* parms; + + /* An array whose size is the number of template arguments. The + elements are non-zero if the argument makes use of template + parameters of this level. */ + int* arg_uses_template_parms; }; /* Subroutine of push_template_decl used to see if each template @@ -1790,13 +1832,205 @@ mark_template_parm (t, data) } if (level == tpd->level) - tpd->parms[idx] = 1; + { + tpd->parms[idx] = 1; + tpd->arg_uses_template_parms[tpd->current_arg] = 1; + } /* Return zero so that for_each_template_parm will continue the traversal of the tree; we want to mark *every* template parm. */ return 0; } +/* Process the partial specialization DECL. */ + +tree +process_partial_specialization (decl) + tree decl; +{ + tree type = TREE_TYPE (decl); + tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); + tree specargs = CLASSTYPE_TI_ARGS (type); + tree inner_args = innermost_args (specargs); + tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); + tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl); + int nargs = TREE_VEC_LENGTH (inner_args); + int ntparms = TREE_VEC_LENGTH (inner_parms); + int i; + int did_error_intro = 0; + int issued_default_arg_message = 0; + struct template_parm_data tpd; + struct template_parm_data tpd2; + + /* [temp.class.spec] + + The template parameter list of a specialization shall not + contain default template argument values. */ + for (i = 0; i < ntparms; ++i) + { + if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i))) + { + if (!issued_default_arg_message) + { + cp_error ("default argument in partial specialization `%T'", + type); + issued_default_arg_message = 1; + } + TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE; + } + } + + /* We check that each of the template parameters given in the + partial specialization is used in the argument list to the + specialization. For example: + + template struct S; + template struct S; + + The second declaration is OK because `T*' uses the template + parameter T, whereas + + template struct S; + + is no good. Even trickier is: + + template + struct S1 + { + template + struct S2; + template + struct S2; + }; + + The S2 declaration is actually illegal; it is a + full-specialization. Of course, + + template + struct S2; + + or some such would have been OK. */ + tpd.level = TMPL_PARMS_DEPTH (current_template_parms); + tpd.parms = alloca (sizeof (int) * ntparms); + bzero (tpd.parms, sizeof (int) * nargs); + + tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs); + bzero (tpd.arg_uses_template_parms, sizeof (int) * nargs); + for (i = 0; i < nargs; ++i) + { + tpd.current_arg = i; + for_each_template_parm (TREE_VEC_ELT (inner_args, i), + &mark_template_parm, + &tpd); + } + for (i = 0; i < ntparms; ++i) + if (tpd.parms[i] == 0) + { + /* One of the template parms was not used in the + specialization. */ + if (!did_error_intro) + { + cp_error ("template parameters not used in partial specialization:"); + did_error_intro = 1; + } + + cp_error (" `%D'", + TREE_VALUE (TREE_VEC_ELT (inner_parms, i))); + } + + /* [temp.class.spec] + + The argument list of the specialization shall not be identical to + the implicit argument list of the primary template. */ + if (comp_template_args (inner_args, + innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE + (maintmpl))))) + cp_error ("partial specialization `%T' does not specialize any template arguments", type); + + /* [temp.class.spec] + + A partially specialized non-type argument expression shall not + involve template parameters of the partial specialization except + when the argument expression is a simple identifier. + + The type of a template parameter corresponding to a specialized + non-type argument shall not be dependent on a parameter of the + specialization. */ + my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0); + tpd2.parms = 0; + for (i = 0; i < nargs; ++i) + { + tree arg = TREE_VEC_ELT (inner_args, i); + if (/* These first two lines are the `non-type' bit. */ + TREE_CODE_CLASS (TREE_CODE (arg)) != 't' + && TREE_CODE (arg) != TEMPLATE_DECL + /* This next line is the `argument expression is not just a + simple identifier' condition and also the `specialized + non-type argument' bit. */ + && TREE_CODE (arg) != TEMPLATE_PARM_INDEX) + { + if (tpd.arg_uses_template_parms[i]) + cp_error ("template argument `%E' involves template parameter(s)", arg); + else + { + /* Look at the corresponding template parameter, + marking which template parameters its type depends + upon. */ + tree type = + TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms, + i))); + + if (!tpd2.parms) + { + /* We haven't yet initialized TPD2. Do so now. */ + tpd2.arg_uses_template_parms + = (int*) alloca (sizeof (int) * nargs); + tpd2.parms = (int*) alloca (sizeof (int) * nargs); + tpd2.level = + TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl)); + } + + /* Mark the template paramters. But this time, we're + looking for the template parameters of the main + template, not in the specialization. */ + tpd2.current_arg = i; + tpd2.arg_uses_template_parms[i] = 0; + bzero (tpd.parms, sizeof (int) * nargs); + for_each_template_parm (type, + &mark_template_parm, + &tpd2); + + if (tpd2.arg_uses_template_parms [i]) + { + /* The type depended on some template parameters. + If they are fully specialized in the + specialization, that's OK. */ + int j; + for (j = 0; j < nargs; ++j) + if (tpd2.parms[j] != 0 + && tpd.arg_uses_template_parms [j]) + { + cp_error ("type `%T' of template argument `%E' depends on template paramter(s)", + type, + arg); + break; + } + } + } + } + } + + if (retrieve_specialization (maintmpl, specargs)) + /* We've already got this specialization. */ + return decl; + + DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type) + = perm_tree_cons (inner_args, inner_parms, + DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); + TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; + return decl; +} + /* Creates a TEMPLATE_DECL for the indicated DECL using the template parameters given by current_template_args, or reuses a previously existing one, if appropriate. Returns the DECL, or an @@ -1868,92 +2102,7 @@ push_template_decl_real (decl, is_friend) if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl) && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))) - { - tree type = TREE_TYPE (decl); - tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); - tree specargs = CLASSTYPE_TI_ARGS (type); - - /* We check that each of the template parameters given in the - partial specialization is used in the argument list to the - specialization. For example: - - template struct S; - template struct S; - - The second declaration is OK because `T*' uses the template - parameter T, whereas - - template struct S; - - is no good. Even trickier is: - - template - struct S1 - { - template - struct S2; - template - struct S2; - }; - - The S2 declaration is actually illegal; it is a - full-specialization. Of course, - - template - struct S2; - - or some such would have been OK. */ - int i; - struct template_parm_data tpd; - int ntparms - = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (current_template_parms)); - int did_error_intro = 0; - - tpd.level = TMPL_PARMS_DEPTH (current_template_parms); - tpd.parms = alloca (sizeof (int) * ntparms); - for (i = 0; i < ntparms; ++i) - tpd.parms[i] = 0; - for (i = 0; i < TREE_VEC_LENGTH (specargs); ++i) - for_each_template_parm (TREE_VEC_ELT (specargs, i), - &mark_template_parm, - &tpd); - for (i = 0; i < ntparms; ++i) - if (tpd.parms[i] == 0) - { - /* One of the template parms was not used in the - specialization. */ - if (!did_error_intro) - { - cp_error ("template parameters not used in partial specialization:"); - did_error_intro = 1; - } - - cp_error (" `%D'", - TREE_VALUE (TREE_VEC_ELT - (TREE_VALUE (current_template_parms), - i))); - } - - /* [temp.class.spec] - - The argument list of the specialization shall not be - identical to the implicit argument list of the primary - template. */ - if (comp_template_args (specargs, - CLASSTYPE_TI_ARGS (TREE_TYPE (maintmpl)))) - cp_error ("partial specialization `%T' does not specialize any template arguments", type); - - if (retrieve_specialization (maintmpl, specargs)) - /* We've already got this specialization. */ - return decl; - - DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type) - = perm_tree_cons (innermost_args (specargs), - INNERMOST_TEMPLATE_PARMS (current_template_parms), - DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); - TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; - return decl; - } + return process_partial_specialization (decl); args = current_template_args (); @@ -5194,7 +5343,6 @@ tsubst_decl (t, args, type, in_decl) return r; } - /* Substitue into the ARG_TYPES of a function type. */ tree @@ -5204,7 +5352,6 @@ tsubst_arg_types (arg_types, args, in_decl) tree in_decl; { tree remaining_arg_types; - tree result; tree type; if (!arg_types || arg_types == void_list_node) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 89aca96b8d9..eee6616698e 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1234,9 +1234,9 @@ begin_class_definition (t) && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL && ! current_class_type) push_template_decl (TYPE_STUB_DECL (t)); + maybe_process_partial_specialization (t); pushclass (t, 0); TYPE_BEING_DEFINED (t) = 1; - maybe_process_partial_specialization (t); /* Reset the interface data, at the earliest possible moment, as it might have been set via a class foo; before. */ diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C index 83ebcc16cc7..0defb196116 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C @@ -5,11 +5,13 @@ struct S { template void foo(T t); - - template <> - void foo(int) {} }; + +template <> +template <> +void S::foo(int) {} + int main() { S s; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C index 73e0e19e85f..fbb79013038 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C @@ -7,13 +7,14 @@ struct S template void foo(T t); - template <> - void foo(int) { } - template void bar(T t) { this->template foo(3.74); } }; +template <> +template <> +void S::foo(int) { } + int main() { S s; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C index 9f714427459..c9282632aa1 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C @@ -4,11 +4,11 @@ struct S { template void foo(T t); - - template <> - void foo(int i) { } }; +template <> +void S::foo(int i) { } + int main() { S s; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C index 08166b0220d..1a5cabe67a1 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C @@ -4,12 +4,13 @@ struct S struct Y { template void foo(T t); - - template <> - void foo(int i) { } }; }; +template <> +template <> +void S::Y::foo(int i) { } + int main() { S::Y s; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C index d67da394c3e..1fdb055b357 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C @@ -4,9 +4,6 @@ struct S { template void foo(T t); - - template <> - void foo(int i); }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C index 2efd4d6d73c..8cfadeffd3e 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C @@ -4,9 +4,6 @@ struct S { template void foo(T t); - - template <> - void foo(int i); }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C index e6f62cfa38d..ca4cf20e7df 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C @@ -7,9 +7,9 @@ struct S3 static char* h(U); }; -template template <> -char* S3::h(int) { return __PRETTY_FUNCTION__; } +template <> +char* S3::h(int) { return __PRETTY_FUNCTION__; } template <> template <> diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec10.C b/gcc/testsuite/g++.old-deja/g++.pt/spec10.C index 10947aa8e8c..5d53e2d76b1 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec10.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec10.C @@ -5,14 +5,15 @@ struct S { template int f(int j) { abort(); return 0; } - - template <> - int f<7>(int j) { return j + 7; } - - template <> - int f<8>(int j) { return j + 8; } }; +template <> +template <> +int S::f<7>(int j) { return j + 7; } + +template <> +template <> +int S::f<8>(int j) { return j + 8; } int main() { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec11.C b/gcc/testsuite/g++.old-deja/g++.pt/spec11.C index 4369f18f15a..340b58e73ec 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec11.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec11.C @@ -7,9 +7,9 @@ struct S int f(U u); }; -template template <> -int S::f(int i) { return 1; } +template <> +int S::f(int i) { return 1; } int main() { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec12.C b/gcc/testsuite/g++.old-deja/g++.pt/spec12.C index 71676ff6cbc..d9c39654e93 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec12.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec12.C @@ -8,9 +8,9 @@ struct S }; -template template <> -int S::f(int i) { return 1; } +template <> +int S::f(int i) { return 1; } int main() { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec13.C b/gcc/testsuite/g++.old-deja/g++.pt/spec13.C index 8f94570db84..e5748f56c14 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec13.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec13.C @@ -14,11 +14,11 @@ struct S1 template void f(T* t); - - template <> - void f(int* ip) {} }; +template <> +void S1::f(int* ip) {} + template struct S2 { @@ -27,11 +27,12 @@ struct S2 template void f(T* t); - - template <> - void f(int* ip) {} }; +template <> +template <> +void S2::f(int* ip) {} + int main() { int* ip; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec15.C b/gcc/testsuite/g++.old-deja/g++.pt/spec15.C index 0aec14336af..2e97b046265 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec15.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec15.C @@ -28,9 +28,9 @@ struct S3 static int h(U); }; -template template <> -int S3::h(int) { return 0; } +template <> +int S3::h(int) { return 0; } template <> template <> diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C new file mode 100644 index 00000000000..497a32d7554 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C @@ -0,0 +1,11 @@ +// Build don't link: + +template +struct S { + template void f(U); + template <> void f(int); // ERROR - specialization + + template struct I {}; + template struct I {}; + template <> struct I; // ERROR - specialization +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec21.C b/gcc/testsuite/g++.old-deja/g++.pt/spec21.C new file mode 100644 index 00000000000..95e12d2f923 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec21.C @@ -0,0 +1,16 @@ +// Build don't link: + +template struct S {}; +template struct S {}; // ERROR - default argument + +template struct A {}; +template struct A {}; // ERROR - argument involves parameter + +template struct C {}; +template struct C; // ERROR - type depends on parameter +int i; +template struct C; // ERROR - type depends on parameter + +template< int X, int (*array_ptr)[X] > class B {}; +int array[5]; +template< int X > class B { }; // ERROR - type depends on parameter diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec22.C b/gcc/testsuite/g++.old-deja/g++.pt/spec22.C new file mode 100644 index 00000000000..88d55d38db6 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec22.C @@ -0,0 +1,15 @@ +// Build don't link: + +template +struct S +{ + template + void f(); +}; + + +template +template <> // ERROR - enclosing classes not specialized +void S::f () +{ +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec6.C b/gcc/testsuite/g++.old-deja/g++.pt/spec6.C index b41ad9d8da6..4ef8e651594 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec6.C @@ -4,21 +4,23 @@ struct S1 { template void f(T t1, T t2); - - template <> - void f(int i1, int i2); }; + +template <> +void S1::f(int i1, int i2); + template struct S2 { template void f(T t1, T t2); - - template <> - void f(int i1, int i2); }; +template <> +template <> +void S2::f(int i1, int i2); + void h() { S1 s1; -- 2.30.2