Hi,
in this error recovery regression, we ICE after (a lot after) a sensible
diagnostic, when lower_function_body encounters an error_mark_node. I
worked quite a bit on the issue, and, all in all, I propose to simply
check the return value of duplicate_decls as called by
register_specialization and bail out.
In principle it may make sense to continue and, for example, also emit
diagnostic about '= default' making sense only for special member
functions - returning spec instead of error_mark_node would achieve that
without regressions for the second testcase - but I'm not sure we want
to do this kind of change right here right now together with fixing the
ICE, because we do *not* emit additional diagnostic in the non-template
case, eg for:
void foo(int) {}
void foo(int) = default;
Tested x86_64-linux.
Thanks, Paolo.
/////////////////////
/cp
2017-02-23 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/79361
* pt.c (register_specialization): Check duplicate_decls return value
for error_mark_node and pass it back.
/testsuite
2017-02-23 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/79361
* g++.dg/cpp0x/pr79361-1.C: New.
* g++.dg/cpp0x/pr79361-2.C: Likewise.
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 245655)
+++ cp/pt.c (working copy)
@@ -1599,7 +1599,12 @@ register_specialization (tree spec, tree tmpl, tre
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- if (!duplicate_decls (spec, fn, is_friend) && DECL_INITIAL (spec))
+ tree dd = duplicate_decls (spec, fn, is_friend);
+ if (dd == error_mark_node)
+ /* We've already complained in duplicate_decls. */
+ return error_mark_node;
+
+ if (dd == NULL_TREE && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new definition. Set the
line number so any errors match this new
definition. */
Index: testsuite/g++.dg/cpp0x/pr79361-1.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr79361-1.C (revision 0)
+++ testsuite/g++.dg/cpp0x/pr79361-1.C (working copy)
@@ -0,0 +1,7 @@
+// PR c++/79361
+// { dg-do compile { target c++11 } }
+
+template<typename T> void foo(T);
+
+template<> void foo<int>(int) {} // { dg-message "declared" }
+template<> void foo<int>(int) = delete; // { dg-error "redefinition" }
Index: testsuite/g++.dg/cpp0x/pr79361-2.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr79361-2.C (revision 0)
+++ testsuite/g++.dg/cpp0x/pr79361-2.C (working copy)
@@ -0,0 +1,7 @@
+// PR c++/79361
+// { dg-do compile { target c++11 } }
+
+template<typename T> void foo(T);
+
+template<> void foo<int>(int) {} // { dg-message "declared" }
+template<> void foo<int>(int) = default; // { dg-error "redefinition" }