From: Nathan Sidwell Date: Mon, 6 Jun 2005 17:29:41 +0000 (+0000) Subject: re PR c++/21903 (Default argument of template function causes a compile-time error) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5e97d404553157c7d74c399907b60125111f130f;p=gcc.git re PR c++/21903 (Default argument of template function causes a compile-time error) cp: PR 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. testsuite: PR 21903 * g++.dg/parse/defarg9.C: New. From-SVN: r100669 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 758451c25c4..e493e10b0f7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2005-06-06 Nathan Sidwell + PR 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++/20637 * cp-tree.h (add_method): Add using_decl parameter. * class.c (add_method): Add using_decl parameter. Adjust error diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index c42dbfbf7c0..27284675e61 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -206,7 +206,9 @@ DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0) /* A using directive. The operand is USING_STMT_NAMESPACE. */ DEFTREECODE (USING_STMT, "using_directive", tcc_statement, 1) -/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */ +/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. + TREE_CHAIN is used to hold instantiations of functions that had to + be instantiated before the argument was parsed. */ DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 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 65442c769d0..c0059d055f6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -15593,19 +15593,29 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) parm = TREE_CHAIN (parm)) { cp_token_cache *tokens; - - if (!TREE_PURPOSE (parm) - || TREE_CODE (TREE_PURPOSE (parm)) != DEFAULT_ARG) + tree default_arg = TREE_PURPOSE (parm); + tree parsed_arg; + + if (!default_arg) continue; + gcc_assert (TREE_CODE (default_arg) == DEFAULT_ARG); + /* Push the saved tokens for the default argument onto the parser's lexer stack. */ - tokens = DEFARG_TOKENS (TREE_PURPOSE (parm)); + tokens = DEFARG_TOKENS (default_arg); cp_parser_push_lexer_for_tokens (parser, tokens); /* Parse the assignment-expression. */ - TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser, - /*cast_p=*/false); + parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false); + + TREE_PURPOSE (parm) = 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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ad1e5f33bfd..7924bbee975 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6704,6 +6704,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; @@ -6731,12 +6733,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 9061d5f9ee5..a89b7fef961 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2005-06-06 Nathan Sidwell + PR 21903 + * g++.dg/parse/defarg9.C: New. + PR c++/20637 * g++.dg/inherit/using4.C: New. * g++.dg/overload/error1.C: Adjust expected errors. diff --git a/gcc/testsuite/g++.dg/parse/defarg9.C b/gcc/testsuite/g++.dg/parse/defarg9.C new file mode 100644 index 00000000000..8496cfb26c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/defarg9.C @@ -0,0 +1,20 @@ +// Copyright (C) 2005 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 6 Jun 2005 + +// PR 21903:Reject legal with default arg confusion +// Origin: Wolfgang Bangerth + + +struct O { + template struct B { + void set (T, bool=true); + }; + + struct D : public B {}; +}; + +void x () +{ + O::D d; + d.set(1); +}