Hi,

this is just an error recovery ICE but maybe we can fix it in time for 9.1.0, like c++/89488, which is somehow related. Indeed, the problem is again a !DEFERRED_NOEXCEPT_SPEC_P gcc_assert triggering where, earlier, process_subob_fn had maybe_instantiate_noexcept returning false (in c++/89448 the assertion triggered almost immediately, when merge_exception_specifiers was called).

Anyway, what we committed for c++/89488 doesn't help here because the error_mark_node assigned to *spec_p is propagated back only up to build_over_call, where mark_used returns false but isn't acted upon because of the additional && !(complain & tf_error). Thus I had the idea of simply removing the latter (by itself a bit invasive at this stage) but that leads to duplicated diagnostics because then, in cp_parser_decltype_expr, when cp_parser_postfix_expression returns error_mark_node we go on and try a full expression too, and emit the same diagnostics again.

Given the above we can imagine reworking the parser, which seems to me a bit tricky at this time, or we can go back to my initial proposal for c++/89488, attached below, which doesn't set *spec_p to error_mark_node when maybe_instantiate_noexcept returns false. My rationale being that, elsewhere, we very often discard completely the return value of maybe_instantiate_noexcept, thus it doesn't seem a big deal only using it to avoid immediately calling marge_exception_specifiers and ICE. If we do this, for c++/89448 we emit the additional "cannot convert" error, which may not be a bad thing, given that we used to emit it forever, and the same do both clang and edg, thus it looks like considering that 'zl ()' not completely broken may make sense for error-recovery purposes...

Tested x86_64-linux.

Thanks, Paolo.

///////////////////////////////

/cp
2019-03-12  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/89571
        * method.c (process_subob_fn): Do not set *spec_p to error_mark_node
        when maybe_instantiate_noexcept returns false.

/testsuite
2019-03-12  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/89571
        * g++.dg/cpp0x/noexcept36.C: New.
        * g++.dg/cpp0x/nsdmi15.C: Adjust.
Index: cp/method.c
===================================================================
--- cp/method.c (revision 269606)
+++ cp/method.c (working copy)
@@ -1254,15 +1254,10 @@ process_subob_fn (tree fn, tree *spec_p, bool *tri
       return;
     }
 
-  if (spec_p)
+  if (spec_p && maybe_instantiate_noexcept (fn))
     {
-      if (!maybe_instantiate_noexcept (fn))
-       *spec_p = error_mark_node;
-      else
-       {
-         tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
-         *spec_p = merge_exception_specifiers (*spec_p, raises);
-       }
+      tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
+      *spec_p = merge_exception_specifiers (*spec_p, raises);
     }
 
   if (!trivial_fn_p (fn) && !dtor_from_ctor)
Index: testsuite/g++.dg/cpp0x/noexcept36.C
===================================================================
--- testsuite/g++.dg/cpp0x/noexcept36.C (nonexistent)
+++ testsuite/g++.dg/cpp0x/noexcept36.C (working copy)
@@ -0,0 +1,22 @@
+// PR c++/89571
+// { dg-do compile { target c++11 } }
+
+struct z8 {
+  constexpr static int qq /* = 0 */;  // { dg-error "initializer" }
+};
+
+template<typename T>
+struct kf {
+  kf (const kf &) noexcept (T::qq);  // { dg-error "constant" }
+};
+
+struct lk {
+  kf<z8> e1;
+};
+
+template<typename T>
+T &sc ();
+
+struct b6 {
+  decltype (lk (sc<lk> ())) zz;
+};
Index: testsuite/g++.dg/cpp0x/nsdmi15.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi15.C    (revision 269606)
+++ testsuite/g++.dg/cpp0x/nsdmi15.C    (working copy)
@@ -3,6 +3,6 @@
 
 struct zl {
   struct {
-    int x2 = zl ();  // { dg-error "default member" }
+    int x2 = zl ();  // { dg-error "default member|cannot convert" }
   } fx;
 };

Reply via email to