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.

	* g++.dg/cpp0x/noexcept38.C: New test.
	* g++.dg/cpp0x/noexcept39.C: New test.
	* g++.dg/cpp1z/noexcept-type21.C: New test.

From-SVN: r270005
This commit is contained in:
Marek Polacek 2019-03-28 20:24:48 +00:00 committed by Marek Polacek
parent ddfd99ac13
commit c526171d73
6 changed files with 112 additions and 28 deletions

View File

@ -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...

View File

@ -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;
}
/* 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;
/* Create substitution entries for the parameters. */
register_parameter_specializations (tdecl, fn);
/* 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);
/* 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);
}
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)

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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, [] {});
}