PR c++/80856 - ICE with local extern in template
authorJason Merrill <jason@redhat.com>
Tue, 30 May 2017 21:13:27 +0000 (17:13 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 30 May 2017 21:13:27 +0000 (17:13 -0400)
* semantics.c (finish_call_expr): Replace a local extern overload
set in a template with the IDENTIFIER_NODE.

From-SVN: r248699

gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/testsuite/g++.dg/template/local-fn2.C [new file with mode: 0644]

index 2dac6109392d6c849ed9f8bf29af9081cf97ec90..8cc3ca39e823f0a89a3f3c4cfeae563fb4045094 100644 (file)
@@ -1,3 +1,9 @@
+2017-05-30  Jason Merrill  <jason@redhat.com>
+
+       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.
+
 2017-05-30  David Malcolm  <dmalcolm@redhat.com>
 
        * call.c (perform_implicit_conversion_flags): Convert
index 87b95345d5cb53f348af007204f51b531783c417..99c61e5fd3c2067a71cafb2135c36936bdeb22b5 100644 (file)
@@ -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 (file)
index 0000000..98525fd
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/80856
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+inline T WrapToCycle(T degrees)
+{
+  int Wrap(int x, int lower_bound, int upper_bound);
+
+  auto p = Wrap;
+  p (1, 0, 360);
+
+  double Wrap(double x, int lower_bound, int upper_bound);
+
+  Wrap(1, 0, 360);
+  return Wrap(degrees, 0, 360);
+}
+
+void GenerateOldReportPage()
+{
+  WrapToCycle(0);
+}