This patch fixes 58582, a set of ICEs that happen instantiating NSDMIs. There
are a couple of causes, both fixed.
1) instantiating the template while parsing an NSDMI of the template itself.
We see a DEFAULT_ARG in get_nsdmi. Fixed by jumping to the existing error
handling for the non-template case.
2) recursive instantiation of the NSDMI itself. As we instantiate lazily, we
end up running out of stack. Fixed by creating a temporary DEFAULT_ARG and then
detecting it on a subsequent recursion. I did contemplate having this direct to
the same error as above, but decided against it, because this really is an
instantiation problem not a parsing problem.
built & tested on x86_64-linux, ok?
nathan
2015-06-05 Nathan Sidwell <nat...@acm.org>
cp/
PR c++/58583
* init.c (get_nsdmi): Check for DEFAULT_ARG in template case and
protect it from recursive instantiation.
testsuite/
PR c++/58583
* g++.dg/cpp0x/nsdmi-template14.C: New test.
Index: cp/init.c
===================================================================
--- cp/init.c (revision 224152)
+++ cp/init.c (working copy)
@@ -544,6 +544,7 @@ get_nsdmi (tree member, bool in_ctor)
tree init;
tree save_ccp = current_class_ptr;
tree save_ccr = current_class_ref;
+
if (!in_ctor)
{
/* Use a PLACEHOLDER_EXPR when we don't have a 'this' parameter to
@@ -551,22 +552,41 @@ get_nsdmi (tree member, bool in_ctor)
current_class_ref = build0 (PLACEHOLDER_EXPR, DECL_CONTEXT (member));
current_class_ptr = build_address (current_class_ref);
}
+
if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
{
- /* Do deferred instantiation of the NSDMI. */
- init = (tsubst_copy_and_build
- (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
- DECL_TI_ARGS (member),
- tf_warning_or_error, member, /*function_p=*/false,
- /*integral_constant_expression_p=*/false));
+ init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
+ if (TREE_CODE (init) == DEFAULT_ARG)
+ goto unparsed;
- init = digest_nsdmi_init (member, init);
+ /* Check recursive instantiation. */
+ if (TREE_CODE (DECL_INITIAL (member)) == DEFAULT_ARG)
+ {
+ error ("recursive instantiation of non-static data member "
+ "initializer for %qD", member);
+ init = error_mark_node;
+ }
+ else
+ {
+ DECL_INITIAL (member) = make_node (DEFAULT_ARG);
+
+ /* Do deferred instantiation of the NSDMI. */
+ init = (tsubst_copy_and_build
+ (init, DECL_TI_ARGS (member),
+ tf_warning_or_error, member, /*function_p=*/false,
+ /*integral_constant_expression_p=*/false));
+ init = digest_nsdmi_init (member, init);
+
+ if (TREE_CODE (DECL_INITIAL (member)) == DEFAULT_ARG)
+ DECL_INITIAL (member) = void_node;
+ }
}
else
{
init = DECL_INITIAL (member);
if (init && TREE_CODE (init) == DEFAULT_ARG)
{
+ unparsed:
error ("constructor required before non-static data member "
"for %qD has been parsed", member);
DECL_INITIAL (member) = error_mark_node;
Index: testsuite/g++.dg/cpp0x/nsdmi-template14.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-template14.C (revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-template14.C (working copy)
@@ -0,0 +1,23 @@
+// PR c++/58583
+// { dg-do compile { target c++11 } }
+
+template<int> struct A // {dg-error "non-static data member initializer" }
+{
+ int i = (A<0>(), 0); // { dg-error "non-static data member initializer required before parsing" } { dg-error "synthesized method" }
+};
+
+template<int N> struct B
+{
+ B* p = new B<N>;
+};
+
+B<1> x; // { dg-error "constructor required before non-static data member" }
+
+struct C
+{
+ template<int N> struct D
+ {
+ D* p = new D<0>;
+ };
+};
+