aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c75
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept38.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept39.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C16
6 files changed, 113 insertions, 29 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 075e977..eb35f9e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2019-03-28 Marek Polacek <polacek@redhat.com>
+ PR c++/89612 - ICE with member friend template with noexcept.
+ * pt.c (maybe_instantiate_noexcept): For function templates, use their
+ template result (function decl). Don't set up local specializations.
+ Temporarily turn on processing_template_decl. Update the template type
+ too.
+
PR c++/89836 - bool constant expression and explicit conversions.
* call.c (build_converted_constant_expr_internal): New function,
renamed from...
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 229b34a..91c3415 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -24193,6 +24193,17 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
if (DECL_CLONED_FUNCTION_P (fn))
fn = DECL_CLONED_FUNCTION (fn);
+
+ tree orig_fn = NULL_TREE;
+ /* For a member friend template we can get a TEMPLATE_DECL. Let's use
+ its FUNCTION_DECL for the rest of this function -- push_access_scope
+ doesn't accept TEMPLATE_DECLs. */
+ if (DECL_FUNCTION_TEMPLATE_P (fn))
+ {
+ orig_fn = fn;
+ fn = DECL_TEMPLATE_RESULT (fn);
+ }
+
fntype = TREE_TYPE (fn);
spec = TYPE_RAISES_EXCEPTIONS (fntype);
@@ -24229,37 +24240,41 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
push_deferring_access_checks (dk_no_deferred);
input_location = DECL_SOURCE_LOCATION (fn);
- /* A new stack interferes with pop_access_scope. */
- {
- /* Set up the list of local specializations. */
- local_specialization_stack lss (lss_copy);
-
- tree save_ccp = current_class_ptr;
- tree save_ccr = current_class_ref;
- /* If needed, set current_class_ptr for the benefit of
- tsubst_copy/PARM_DECL. */
- tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn));
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl))
- {
- tree this_parm = DECL_ARGUMENTS (tdecl);
- current_class_ptr = NULL_TREE;
- current_class_ref = cp_build_fold_indirect_ref (this_parm);
- current_class_ptr = this_parm;
- }
+ tree save_ccp = current_class_ptr;
+ tree save_ccr = current_class_ref;
+ /* If needed, set current_class_ptr for the benefit of
+ tsubst_copy/PARM_DECL. */
+ tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn));
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl))
+ {
+ tree this_parm = DECL_ARGUMENTS (tdecl);
+ current_class_ptr = NULL_TREE;
+ current_class_ref = cp_build_fold_indirect_ref (this_parm);
+ current_class_ptr = this_parm;
+ }
- /* Create substitution entries for the parameters. */
- register_parameter_specializations (tdecl, fn);
+ /* If this function is represented by a TEMPLATE_DECL, then
+ the deferred noexcept-specification might still contain
+ dependent types, even after substitution. And we need the
+ dependency check functions to work in build_noexcept_spec. */
+ if (orig_fn)
+ ++processing_template_decl;
- /* Do deferred instantiation of the noexcept-specifier. */
- noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
- DEFERRED_NOEXCEPT_ARGS (noex),
- tf_warning_or_error, fn,
- /*function_p=*/false,
- /*i_c_e_p=*/true);
- current_class_ptr = save_ccp;
- current_class_ref = save_ccr;
- spec = build_noexcept_spec (noex, tf_warning_or_error);
- }
+ /* Do deferred instantiation of the noexcept-specifier. */
+ noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
+ DEFERRED_NOEXCEPT_ARGS (noex),
+ tf_warning_or_error, fn,
+ /*function_p=*/false,
+ /*i_c_e_p=*/true);
+
+ current_class_ptr = save_ccp;
+ current_class_ref = save_ccr;
+
+ /* Build up the noexcept-specification. */
+ spec = build_noexcept_spec (noex, tf_warning_or_error);
+
+ if (orig_fn)
+ --processing_template_decl;
pop_deferring_access_checks ();
pop_access_scope (fn);
@@ -24279,6 +24294,8 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
}
TREE_TYPE (fn) = build_exception_variant (fntype, spec);
+ if (orig_fn)
+ TREE_TYPE (orig_fn) = TREE_TYPE (fn);
}
FOR_EACH_CLONE (clone, fn)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cf9ed5c..9a496ec 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2019-03-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/89612 - ICE with member friend template with noexcept.
+ * g++.dg/cpp0x/noexcept38.C: New test.
+ * g++.dg/cpp0x/noexcept39.C: New test.
+ * g++.dg/cpp1z/noexcept-type21.C: New test.
+
2019-03-28 Uroš Bizjak <ubizjak@gmail.com>
PR target/89848
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept38.C b/gcc/testsuite/g++.dg/cpp0x/noexcept38.C
new file mode 100644
index 0000000..ecab59d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept38.C
@@ -0,0 +1,19 @@
+// PR c++/89612
+// { dg-do compile { target c++11 } }
+
+template <typename>
+struct C {
+ template <int N>
+ friend int foo() noexcept(N);
+
+ template <int N>
+ friend int foo2() noexcept(N); // { dg-error "different exception" }
+};
+
+template <int N>
+int foo() noexcept(N);
+
+template <int N>
+int foo2() noexcept(N + 1);
+
+C<int> c;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept39.C b/gcc/testsuite/g++.dg/cpp0x/noexcept39.C
new file mode 100644
index 0000000..fbebbed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept39.C
@@ -0,0 +1,19 @@
+// PR c++/89612
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+struct C {
+ template <int N>
+ friend void foo(T t) noexcept(sizeof(decltype(t)) > 1);
+
+ template <int N>
+ friend void foo2(T t) noexcept(sizeof(decltype(t)) < 1); // { dg-error "different exception" }
+};
+
+template <int N>
+void foo(int i) noexcept { }
+
+template <int N>
+void foo2(int i) noexcept { }
+
+C<int> c;
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C
new file mode 100644
index 0000000..d0a61d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C
@@ -0,0 +1,16 @@
+// PR c++/89612
+// { dg-do compile { target c++17 } }
+
+template <typename a> using b = typename a ::c;
+template <typename> bool d;
+template <typename, typename> struct e {
+ template <typename f, typename g> e(f, g) {}
+ template <typename h, typename i, typename j>
+ friend auto k(h &&, const j &, i &&) noexcept(d<b<h>, h> &&d<b<i>, i>);
+};
+template <typename l, typename m> e(l, m)->e<l, m>;
+template <typename l, typename m, typename j>
+auto k(l &&, const j &, m &&) noexcept(d<b<l>, l> &&d<b<m>, m>);
+int main() {
+ e(0, [] {});
+}