My patch for 10200 caused finish_id_expression for Wrap to return the actual overload set rather than the plain identifier, and we stored that set in the template CALL_EXPR, but then at instantiation time we failed to go through and replace it with the instantiated overload set. This patch avoids this problem by reverting to the identifier when we build the CALL_EXPR.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 32c5b130ecdc5eaa6287e1be3abd0794b4bcd129 Author: Jason Merrill <ja...@redhat.com> Date: Tue May 30 15:31:38 2017 -0400 PR c++/80856 - ICE with local extern in template * semantics.c (finish_call_expr): Replace a local extern overload set in a template with the IDENTIFIER_NODE. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ae03ef6..7269c09 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2316,13 +2316,23 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, if (processing_template_decl) { + /* If FN is a local extern declaration or set thereof, look them up + again at instantiation time. */ + if (is_overloaded_fn (fn)) + { + tree ifn = get_first_fn (fn); + if (TREE_CODE (ifn) == FUNCTION_DECL + && DECL_LOCAL_FUNCTION_P (ifn)) + orig_fn = DECL_NAME (ifn); + } + /* If the call expression is dependent, build a CALL_EXPR node with no type; type_dependent_expression_p recognizes expressions with no type as being dependent. */ if (type_dependent_expression_p (fn) || any_type_dependent_arguments_p (*args)) { - result = build_min_nt_call_vec (fn, *args); + result = build_min_nt_call_vec (orig_fn, *args); SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location)); KOENIG_LOOKUP_P (result) = koenig_p; if (is_overloaded_fn (fn)) diff --git a/gcc/testsuite/g++.dg/template/local-fn2.C b/gcc/testsuite/g++.dg/template/local-fn2.C new file mode 100644 index 0000000..46fd6cf --- /dev/null +++ b/gcc/testsuite/g++.dg/template/local-fn2.C @@ -0,0 +1,16 @@ +// PR c++/80856 + +template<typename T> +inline T WrapToCycle(T degrees) +{ + int Wrap(int x, int lower_bound, int upper_bound); + double Wrap(double x, int lower_bound, int upper_bound); + + Wrap(1, 0, 360); + return Wrap(degrees, 0, 360); +} + +void GenerateOldReportPage() +{ + WrapToCycle(0); +}