From 02522a5c6efe0452d0b489f27fa032f2ee2d6667 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 9 Jun 2005 07:46:23 +0000 Subject: [PATCH] re PR c++/21903 (Default argument of template function causes a compile-time error) cp: PR c++/21903 * cp-tree.def (DEFAULT_ARG): Document TREE_CHAIN use. * parser.c (cp_parser_late_parsing_default_args): Propagate parsed argument to any early instantiations. * pt.c (tsubst_arg_types): Chain early instantiation of default arg. PR c++/19884 * pt.c (check_explicit_specialization): Make sure namespace binding lookup found an overloaded function. (lookup_template_function): Just assert FNS is an overloaded function. testsuite: PR c++/19608 * parser.c (cp_parser_late_parsing_for_member): Use current_function_decl as scope to push to and from. testsuite: PR 21903 * g++.dg/parse/defarg9.C: New. PR c++/19884 * g++.old-deja/g++.oliva/template6.C: Add another case. * g++.dg/template/explicit6.C: New. PR c++/19608 * g++.dg/parse/local-class1.C: New. From-SVN: r100794 --- gcc/cp/ChangeLog | 20 ++++++++ gcc/cp/cp-tree.def | 4 +- gcc/cp/parser.c | 47 +++++++++++++------ gcc/cp/pt.c | 47 ++++++++++++------- gcc/testsuite/ChangeLog | 12 +++++ .../g++.old-deja/g++.oliva/template6.C | 5 +- 6 files changed, 100 insertions(+), 35 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6853265500a2..3197c669bfdd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,23 @@ +2005-06-08 Nathan Sidwell + + PR c++/21903 + * cp-tree.def (DEFAULT_ARG): Document TREE_CHAIN use. + * parser.c (cp_parser_late_parsing_default_args): Propagate parsed + argument to any early instantiations. + * pt.c (tsubst_arg_types): Chain early instantiation of default + arg. + + PR c++/19884 + * pt.c (check_explicit_specialization): Make sure namespace + binding lookup found an overloaded function. + (lookup_template_function): Just assert FNS is an overloaded + function. + + PR c++/19608 + * parser.c (cp_parser_late_parsing_for_member): Use + current_function_decl as scope to push to and from. + testsuite: + 2005-06-08 Volker Reichelt PR c++/20563 diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 36b7aaa85e83..f6a2bee8d579 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -203,7 +203,9 @@ DEFTREECODE (USING_DECL, "using_decl", 'd', 0) /* A using directive. The operand is USING_STMT_NAMESPACE. */ DEFTREECODE (USING_STMT, "using_directive", 'e', 1) -/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */ +/* An un-parsed default argument. + TREE_CHAIN is used to hold instantiations of functions that had to + be instantiated before the argument was parsed. */ DEFTREECODE (DEFAULT_ARG, "default_arg", 'x', 0) /* A template-id, like foo. The first operand is the template. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8765ff10e69e..d4ca762aba74 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -14771,9 +14771,10 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) tokens = DECL_PENDING_INLINE_INFO (member_function); DECL_PENDING_INLINE_INFO (member_function) = NULL; DECL_PENDING_INLINE_P (member_function) = 0; - /* If this was an inline function in a local class, enter the scope - of the containing function. */ - function_scope = decl_function_context (member_function); + + /* If this is a local class, enter the scope of the containing + function. */ + function_scope = current_function_decl; if (function_scope) push_function_context_to (function_scope); @@ -14854,33 +14855,49 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) parameters; parameters = TREE_CHAIN (parameters)) { - if (!TREE_PURPOSE (parameters) - || TREE_CODE (TREE_PURPOSE (parameters)) != DEFAULT_ARG) + tree default_arg = TREE_PURPOSE (parameters); + tree parsed_arg; + + if (!default_arg) + continue; + + if (TREE_CODE (default_arg) != DEFAULT_ARG) + /* This can happen for a friend declaration for a function + already declared with default arguments. */ continue; - /* Save away the current lexer. */ + /* Save away the current lexer. */ saved_lexer = parser->lexer; - /* Create a new one, using the tokens we have saved. */ - tokens = DEFARG_TOKENS (TREE_PURPOSE (parameters)); + /* Create a new one, using the tokens we have saved. */ + tokens = DEFARG_TOKENS (default_arg); parser->lexer = cp_lexer_new_from_tokens (tokens); - /* Set the current source position to be the location of the - first token in the default argument. */ + /* Set the current source position to be the location of the + first token in the default argument. */ cp_lexer_peek_token (parser->lexer); - /* Local variable names (and the `this' keyword) may not appear - in a default argument. */ + /* Local variable names (and the `this' keyword) may not appear + in a default argument. */ saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; parser->local_variables_forbidden_p = true; - /* Parse the assignment-expression. */ + + /* Parse the assignment-expression. */ if (DECL_FRIEND_CONTEXT (fn)) push_nested_class (DECL_FRIEND_CONTEXT (fn)); else if (DECL_CLASS_SCOPE_P (fn)) push_nested_class (DECL_CONTEXT (fn)); - TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser); + parsed_arg = cp_parser_assignment_expression (parser); if (DECL_FRIEND_CONTEXT (fn) || DECL_CLASS_SCOPE_P (fn)) pop_nested_class (); - + + TREE_PURPOSE (parameters) = parsed_arg; + + /* Update any instantiations we've already created. */ + for (default_arg = TREE_CHAIN (default_arg); + default_arg; + default_arg = TREE_CHAIN (default_arg)) + TREE_PURPOSE (TREE_PURPOSE (default_arg)) = parsed_arg; + /* If the token stream has not been completely used up, then there was extra junk after the end of the default argument. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d3cc61e9d277..ac0f8ceae288 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1779,6 +1779,11 @@ check_explicit_specialization (tree declarator, /* Find the namespace binding, using the declaration context. */ fns = namespace_binding (dname, CP_DECL_CONTEXT (decl)); + if (!fns || !is_overloaded_fn (fns)) + { + error ("`%D' is not a template function", dname); + fns = error_mark_node; + } } declarator = lookup_template_function (fns, NULL_TREE); @@ -4066,18 +4071,9 @@ lookup_template_function (tree fns, tree arglist) return error_mark_node; my_friendly_assert (!arglist || TREE_CODE (arglist) == TREE_VEC, 20030726); - if (fns == NULL_TREE - || TREE_CODE (fns) == FUNCTION_DECL) - { - error ("non-template used as template"); - return error_mark_node; - } - - my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL - || TREE_CODE (fns) == OVERLOAD - || BASELINK_P (fns) - || TREE_CODE (fns) == IDENTIFIER_NODE, - 20020730); + my_friendly_assert (fns && (is_overloaded_fn (fns) + || TREE_CODE (fns) == IDENTIFIER_NODE), + 20050608); if (BASELINK_P (fns)) { @@ -6484,6 +6480,8 @@ tsubst_arg_types (tree arg_types, { tree remaining_arg_types; tree type; + tree default_arg; + tree result = NULL_TREE; if (!arg_types || arg_types == void_list_node) return arg_types; @@ -6511,12 +6509,25 @@ tsubst_arg_types (tree arg_types, top-level qualifiers as required. */ type = TYPE_MAIN_VARIANT (type_decays_to (type)); - /* Note that we do not substitute into default arguments here. The - standard mandates that they be instantiated only when needed, - which is done in build_over_call. */ - return hash_tree_cons (TREE_PURPOSE (arg_types), type, - remaining_arg_types); - + /* We do not substitute into default arguments here. The standard + mandates that they be instantiated only when needed, which is + done in build_over_call. */ + default_arg = TREE_PURPOSE (arg_types); + + if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG) + { + /* We've instantiated a template before its default arguments + have been parsed. This can happen for a nested template + class, and is not an error unless we require the default + argument in a call of this function. */ + result = tree_cons (default_arg, type, remaining_arg_types); + TREE_CHAIN (default_arg) = tree_cons (result, NULL_TREE, + TREE_CHAIN (default_arg)); + } + else + result = hash_tree_cons (default_arg, type, remaining_arg_types); + + return result; } /* Substitute into a FUNCTION_TYPE or METHOD_TYPE. This routine does diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d357b42bad50..95284782d31c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2005-06-08 Nathan Sidwell + + PR c++/21903 + * g++.dg/parse/defarg9.C: New. + + PR c++/19884 + * g++.old-deja/g++.oliva/template6.C: Add another case. + * g++.dg/template/explicit6.C: New. + + PR c++/19608 + * g++.dg/parse/local-class1.C: New. + 2005-06-08 Eric Botcazou * gcc.dg/tls/debug-1.c: New test. diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/template6.C b/gcc/testsuite/g++.old-deja/g++.oliva/template6.C index f31d677afb0f..270d67695f64 100644 --- a/gcc/testsuite/g++.old-deja/g++.oliva/template6.C +++ b/gcc/testsuite/g++.old-deja/g++.oliva/template6.C @@ -6,4 +6,7 @@ // simplified from bug report by Meenaradchagan Vishnu template struct foo {}; -template <> void foo(); // { dg-error "" } bad specialization +template <> void foo(); // { dg-error "not a template function" } bad specialization + +struct baz {}; +template <> void baz (); // { dg-error "not a template function" } bad specialization -- 2.47.2