]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: dependence of member noexcept-spec [PR104079]
authorPatrick Palka <ppalka@redhat.com>
Thu, 3 Feb 2022 23:54:23 +0000 (18:54 -0500)
committerPatrick Palka <ppalka@redhat.com>
Thu, 7 Apr 2022 19:12:38 +0000 (15:12 -0400)
Here a stale TYPE_DEPENDENT_P/_P_VALID value for f's function type
after replacing the type's DEFERRED_NOEXCEPT with the parsed dependent
noexcept-spec causes us to try to instantiate g's noexcept-spec ahead
of time (since it in turn appears non-dependent), leading to an ICE.

This patch fixes this by clearing TYPE_DEPENDENT_P_VALID in
fixup_deferred_exception_variants appropriately (as in
build_cp_fntype_variant).

That turns out to fix the testcase for C++17 but not for C++11/14,
because it's not until C++17 that a noexcept-spec is part of (and
therefore affects dependence of) the function type.  Since dependence of
NOEXCEPT_EXPR is defined in terms of instantiation dependence, the most
appropriate fix for earlier dialects seems to be to make instantiation
dependence consider dependence of a noexcept-spec.

PR c++/104079

gcc/cp/ChangeLog:

* pt.c (value_dependent_noexcept_spec_p): New predicate split
out from ...
(dependent_type_p_r): ... here.
(instantiation_dependent_r): Use value_dependent_noexcept_spec_p
to consider dependence of a noexcept-spec before C++17.
* tree.c (fixup_deferred_exception_variants): Clear
TYPE_DEPENDENT_P_VALID.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept74.C: New test.
* g++.dg/cpp0x/noexcept74a.C: New test.

(cherry picked from commit 82e31c8973eb1a752c2ffd01005efe291d35cee3)

gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/cpp0x/noexcept74.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/noexcept74a.C [new file with mode: 0644]

index 9aadda8d79bc092917a6c793031a7b11c301b06d..c208985e9fb9b5dbfa53225d31f30287c1a5891d 100644 (file)
@@ -26677,6 +26677,24 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
   return true;
 }
 
+/* Returns true iff the noexcept-specifier for TYPE is value-dependent.  */
+
+static bool
+value_dependent_noexcept_spec_p (tree type)
+{
+  if (tree spec = TYPE_RAISES_EXCEPTIONS (type))
+    if (tree noex = TREE_PURPOSE (spec))
+      /* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't
+        affect overload resolution and treating it as dependent breaks
+        things.  Same for an unparsed noexcept expression.  */
+      if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
+         && TREE_CODE (noex) != DEFERRED_PARSE
+         && value_dependent_expression_p (noex))
+       return true;
+
+  return false;
+}
+
 /* Returns TRUE if TYPE is dependent, in the sense of [temp.dep.type].
    Assumes that TYPE really is a type, and not the ERROR_MARK_NODE.*/
 
@@ -26729,17 +26747,10 @@ dependent_type_p_r (tree type)
           arg_type = TREE_CHAIN (arg_type))
        if (dependent_type_p (TREE_VALUE (arg_type)))
          return true;
-      if (cxx_dialect >= cxx17)
+      if (cxx_dialect >= cxx17
+         && value_dependent_noexcept_spec_p (type))
        /* A value-dependent noexcept-specifier makes the type dependent.  */
-       if (tree spec = TYPE_RAISES_EXCEPTIONS (type))
-         if (tree noex = TREE_PURPOSE (spec))
-           /* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't
-              affect overload resolution and treating it as dependent breaks
-              things.  Same for an unparsed noexcept expression.  */
-           if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
-               && TREE_CODE (noex) != DEFERRED_PARSE
-               && value_dependent_expression_p (noex))
-             return true;
+       return true;
       return false;
     }
   /* -- an array type constructed from any dependent type or whose
@@ -27545,6 +27556,17 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
        return *tp;
       break;
 
+    case TEMPLATE_DECL:
+    case FUNCTION_DECL:
+      /* Before C++17, a noexcept-specifier isn't part of the function type
+        so it doesn't affect type dependence, but we still want to consider it
+        for instantiation dependence.  */
+      if (cxx_dialect < cxx17
+         && DECL_DECLARES_FUNCTION_P (*tp)
+         && value_dependent_noexcept_spec_p (TREE_TYPE (*tp)))
+       return *tp;
+      break;
+
     default:
       break;
     }
index 33ac4f2302805b1e5466a3e70692a33b4fa9b9ae..f67ede337c8e0116178b42b754624229a0b3349e 100644 (file)
@@ -2804,6 +2804,10 @@ fixup_deferred_exception_variants (tree type, tree raises)
          }
        else
          TYPE_RAISES_EXCEPTIONS (variant) = raises;
+
+       if (!TYPE_DEPENDENT_P (variant))
+         /* We no longer know that it's not type-dependent.  */
+         TYPE_DEPENDENT_P_VALID (variant) = false;
       }
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept74.C b/gcc/testsuite/g++.dg/cpp0x/noexcept74.C
new file mode 100644 (file)
index 0000000..c439c9d
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/104079
+// { dg-do compile { target c++11 } }
+
+template<bool B>
+struct AT {
+  static void f() noexcept(B);
+
+  void g() noexcept(noexcept(f())) {
+    static_assert(noexcept(f()), "");
+  }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept74a.C b/gcc/testsuite/g++.dg/cpp0x/noexcept74a.C
new file mode 100644 (file)
index 0000000..008654d
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/104079
+// { dg-do compile { target c++11 } }
+// A variant of noexcept74.C where f is a function template.
+
+template<bool B>
+struct AT {
+  template<class...> static void f() noexcept(B);
+
+  void g() noexcept(noexcept(f())) {
+    static_assert(noexcept(f()), "");
+  }
+};