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" }

Reply via email to