aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@gcc.gnu.org>2011-03-15 14:27:09 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-03-15 14:27:09 -0400
commit4c66d85a558f15893d846c0d7d5e9885b8cdf842 (patch)
tree37f9886968ac0a2a5f0f68d1dc00396a32a27f3f
parent56b67510587aa6aa75884ee45f4ddd9108bde7c3 (diff)
downloadgcc-4c66d85a558f15893d846c0d7d5e9885b8cdf842.zip
gcc-4c66d85a558f15893d846c0d7d5e9885b8cdf842.tar.gz
gcc-4c66d85a558f15893d846c0d7d5e9885b8cdf842.tar.bz2
re PR c++/34758 (Bad diagnostic for circular dependency in constructor default argument)
PR c++/34758 * call.c (convert_default_arg): Use DECL_ORIGIN of fn. Check for recursion first. (push_defarg_context, pop_defarg_context): New. * parser.c (cp_parser_late_parsing_default_args): Use them. * cp-tree.h: Declare them. From-SVN: r171009
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c36
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/parser.c4
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/parse/pr34758.C28
6 files changed, 70 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bebb1fc..34a3a53 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2011-03-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/34758
+ * call.c (convert_default_arg): Use DECL_ORIGIN of fn. Check for
+ recursion first.
+ (push_defarg_context, pop_defarg_context): New.
+ * parser.c (cp_parser_late_parsing_default_args): Use them.
+ * cp-tree.h: Declare them.
+
2011-03-11 Dodji Seketeli <dodji@redhat.com>
* call.c (add_builtin_candidate)<case INDIRECT_REF>: The type of
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 5953e35..499ed03 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5746,10 +5746,17 @@ cxx_type_promotes_to (tree type)
}
/* ARG is a default argument expression being passed to a parameter of
- the indicated TYPE, which is a parameter to FN. Do any required
- conversions. Return the converted value. */
+ the indicated TYPE, which is a parameter to FN. PARMNUM is the
+ zero-based argument number. Do any required conversions. Return
+ the converted value. */
static GTY(()) VEC(tree,gc) *default_arg_context;
+void
+push_defarg_context (tree fn)
+{ VEC_safe_push (tree, gc, default_arg_context, fn); }
+void
+pop_defarg_context (void)
+{ VEC_pop (tree, default_arg_context); }
tree
convert_default_arg (tree type, tree arg, tree fn, int parmnum)
@@ -5757,15 +5764,8 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum)
int i;
tree t;
- /* If the ARG is an unparsed default argument expression, the
- conversion cannot be performed. */
- if (TREE_CODE (arg) == DEFAULT_ARG)
- {
- error ("the default argument for parameter %d of %qD has "
- "not yet been parsed",
- parmnum, fn);
- return error_mark_node;
- }
+ /* See through clones. */
+ fn = DECL_ORIGIN (fn);
/* Detect recursion. */
FOR_EACH_VEC_ELT (tree, default_arg_context, i, t)
@@ -5774,7 +5774,17 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum)
error ("recursive evaluation of default argument for %q#D", fn);
return error_mark_node;
}
- VEC_safe_push (tree, gc, default_arg_context, fn);
+
+ /* If the ARG is an unparsed default argument expression, the
+ conversion cannot be performed. */
+ if (TREE_CODE (arg) == DEFAULT_ARG)
+ {
+ error ("call to %qD uses the default argument for parameter %P, which "
+ "is not yet defined", fn, parmnum);
+ return error_mark_node;
+ }
+
+ push_defarg_context (fn);
if (fn && DECL_TEMPLATE_INFO (fn))
arg = tsubst_default_argument (fn, type, arg);
@@ -5814,7 +5824,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum)
}
pop_deferring_access_checks();
- VEC_pop (tree, default_arg_context);
+ pop_defarg_context ();
return arg;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4b49046..6ef6e6e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4638,6 +4638,8 @@ extern bool can_convert (tree, tree);
extern bool can_convert_arg (tree, tree, tree, int);
extern bool can_convert_arg_bad (tree, tree, tree, int);
extern bool enforce_access (tree, tree, tree);
+extern void push_defarg_context (tree);
+extern void pop_defarg_context (void);
extern tree convert_default_arg (tree, tree, tree, int);
extern tree convert_arg_to_ellipsis (tree);
extern tree build_x_va_arg (tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4260f6d..a9fd201 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -20521,6 +20521,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
+ push_defarg_context (fn);
+
for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)),
parmdecl = DECL_ARGUMENTS (fn);
parm && parm != void_list_node;
@@ -20579,6 +20581,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
cp_parser_pop_lexer (parser);
}
+ pop_defarg_context ();
+
/* Make sure no default arg is missing. */
check_default_args (fn);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3947797..3529a65 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-03-15 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ * g++.dg/parse/pr34758.C: New.
+
2011-03-15 Xinliang David Li <davidxl@google.com>
PR c/47837
diff --git a/gcc/testsuite/g++.dg/parse/pr34758.C b/gcc/testsuite/g++.dg/parse/pr34758.C
new file mode 100644
index 0000000..d694853
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr34758.C
@@ -0,0 +1,28 @@
+// PR 34758 Bad diagnostic for circular dependency in constructor default argument
+// { dg-do compile }
+// { dg-options "" }
+struct A
+{
+ A (const A& = A()); // { dg-error "recursive evaluation of default argument" }
+};
+
+
+struct S {
+ S(const S& = f()); // { dg-error "default argument\[^\n\]*which is not yet defined" }
+ static const S& f(int i = 3);
+};
+
+struct J {
+ J(const J& = f(2)); // { dg-error "default argument.*which is not yet defined" }
+ static const J& f(int i = 3, int j = 4);
+};
+
+struct Z {
+ Z(const Z& = f(4));
+ static const Z& f(int i = 3);
+};
+
+struct X {
+ X(const X& = g());
+ static const X& g(void);
+};