aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2005-06-06 17:29:41 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2005-06-06 17:29:41 +0000
commit5e97d404553157c7d74c399907b60125111f130f (patch)
treed1edb6ce6bd660310edc4d54628d90e79e651a0b /gcc
parent2fecaef4af7206fbae14906000e8c81007514706 (diff)
downloadgcc-5e97d404553157c7d74c399907b60125111f130f.zip
gcc-5e97d404553157c7d74c399907b60125111f130f.tar.gz
gcc-5e97d404553157c7d74c399907b60125111f130f.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/parser.c22
-rw-r--r--gcc/cp/pt.c27
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/parse/defarg9.C20
6 files changed, 69 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 758451c..e493e10 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2005-06-06 Nathan Sidwell <nathan@codesourcery.com>
+ 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 c42dbfb..2728467 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<int>. The first operand is the template.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 65442c7..c0059d0 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 ad1e5f3..7924bbe 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 9061d5f..a89b7fe 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2005-06-06 Nathan Sidwell <nathan@codesourcery.com>
+ 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 0000000..8496cfb
--- /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 <nathan@codesourcery.com>
+
+// PR 21903:Reject legal with default arg confusion
+// Origin: Wolfgang Bangerth <bangerth@dealii.org>
+
+
+struct O {
+ template<typename T> struct B {
+ void set (T, bool=true);
+ };
+
+ struct D : public B<int> {};
+};
+
+void x ()
+{
+ O::D d;
+ d.set(1);
+}